1//===-- runtime/reduce.cpp ------------------------------------------------===//
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// REDUCE() implementation
10
11#include "flang/Runtime/reduce.h"
12#include "reduction-templates.h"
13#include "terminator.h"
14#include "tools.h"
15#include "flang/Runtime/descriptor.h"
16
17namespace Fortran::runtime {
18
19template <typename T> class ReduceAccumulator {
20public:
21 RT_API_ATTRS ReduceAccumulator(const Descriptor &array,
22 ReductionOperation<T> operation, const T *identity,
23 Terminator &terminator)
24 : array_{array}, operation_{operation}, identity_{identity},
25 terminator_{terminator} {}
26 RT_API_ATTRS void Reinitialize() { result_.reset(); }
27 template <typename A>
28 RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) {
29 const auto *operand{array_.Element<A>(at)};
30 if (result_) {
31 result_ = operation_(&*result_, operand);
32 } else {
33 result_ = *operand;
34 }
35 return true;
36 }
37 template <typename A>
38 RT_API_ATTRS void GetResult(A *to, int /*zeroBasedDim*/ = -1) {
39 if (result_) {
40 *to = *result_;
41 } else if (identity_) {
42 *to = *identity_;
43 } else {
44 terminator_.Crash("REDUCE() without IDENTITY= has no result");
45 }
46 }
47
48private:
49 const Descriptor &array_;
50 common::optional<T> result_;
51 ReductionOperation<T> operation_;
52 const T *identity_{nullptr};
53 Terminator &terminator_;
54};
55
56template <typename T, typename OP, bool hasLength>
57class BufferedReduceAccumulator {
58public:
59 RT_API_ATTRS BufferedReduceAccumulator(const Descriptor &array, OP operation,
60 const T *identity, Terminator &terminator)
61 : array_{array}, operation_{operation}, identity_{identity},
62 terminator_{terminator} {}
63 RT_API_ATTRS void Reinitialize() { activeTemp_ = -1; }
64 template <typename A>
65 RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) {
66 const auto *operand{array_.Element<A>(at)};
67 if (activeTemp_ >= 0) {
68 if constexpr (hasLength) {
69 operation_(&*temp_[1 - activeTemp_], length_, &*temp_[activeTemp_],
70 operand, length_, length_);
71 } else {
72 operation_(&*temp_[1 - activeTemp_], &*temp_[activeTemp_], operand);
73 }
74 activeTemp_ = 1 - activeTemp_;
75 } else {
76 activeTemp_ = 0;
77 std::memcpy(&*temp_[activeTemp_], operand, elementBytes_);
78 }
79 return true;
80 }
81 template <typename A>
82 RT_API_ATTRS void GetResult(A *to, int /*zeroBasedDim*/ = -1) {
83 if (activeTemp_ >= 0) {
84 std::memcpy(to, &*temp_[activeTemp_], elementBytes_);
85 } else if (identity_) {
86 std::memcpy(dest: to, src: identity_, n: elementBytes_);
87 } else {
88 terminator_.Crash("REDUCE() without IDENTITY= has no result");
89 }
90 }
91
92private:
93 const Descriptor &array_;
94 OP operation_;
95 const T *identity_{nullptr};
96 Terminator &terminator_;
97 std::size_t elementBytes_{array_.ElementBytes()};
98 OwningPtr<T> temp_[2]{SizedNew<T>{terminator_}(elementBytes_),
99 SizedNew<T>{terminator_}(elementBytes_)};
100 int activeTemp_{-1};
101 std::size_t length_{elementBytes_ / sizeof(T)};
102};
103
104extern "C" {
105RT_EXT_API_GROUP_BEGIN
106
107std::int8_t RTDEF(ReduceInteger1)(const Descriptor &array,
108 ReductionOperation<std::int8_t> operation, const char *source, int line,
109 int dim, const Descriptor *mask, const std::int8_t *identity,
110 bool ordered) {
111 Terminator terminator{source, line};
112 return GetTotalReduction<TypeCategory::Integer, 1>(array, source, line, dim,
113 mask,
114 ReduceAccumulator<std::int8_t>{array, operation, identity, terminator},
115 "REDUCE");
116}
117void RTDEF(ReduceInteger1Dim)(Descriptor &result, const Descriptor &array,
118 ReductionOperation<std::int8_t> operation, const char *source, int line,
119 int dim, const Descriptor *mask, const std::int8_t *identity,
120 bool ordered) {
121 Terminator terminator{source, line};
122 using Accumulator = ReduceAccumulator<std::int8_t>;
123 Accumulator accumulator{array, operation, identity, terminator};
124 PartialReduction<Accumulator, TypeCategory::Integer, 1>(result, array,
125 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
126}
127std::int16_t RTDEF(ReduceInteger2)(const Descriptor &array,
128 ReductionOperation<std::int16_t> operation, const char *source, int line,
129 int dim, const Descriptor *mask, const std::int16_t *identity,
130 bool ordered) {
131 Terminator terminator{source, line};
132 return GetTotalReduction<TypeCategory::Integer, 2>(array, source, line, dim,
133 mask,
134 ReduceAccumulator<std::int16_t>{array, operation, identity, terminator},
135 "REDUCE");
136}
137void RTDEF(ReduceInteger2Dim)(Descriptor &result, const Descriptor &array,
138 ReductionOperation<std::int16_t> operation, const char *source, int line,
139 int dim, const Descriptor *mask, const std::int16_t *identity,
140 bool ordered) {
141 Terminator terminator{source, line};
142 using Accumulator = ReduceAccumulator<std::int16_t>;
143 Accumulator accumulator{array, operation, identity, terminator};
144 PartialReduction<Accumulator, TypeCategory::Integer, 2>(result, array,
145 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
146}
147std::int32_t RTDEF(ReduceInteger4)(const Descriptor &array,
148 ReductionOperation<std::int32_t> operation, const char *source, int line,
149 int dim, const Descriptor *mask, const std::int32_t *identity,
150 bool ordered) {
151 Terminator terminator{source, line};
152 return GetTotalReduction<TypeCategory::Integer, 4>(array, source, line, dim,
153 mask,
154 ReduceAccumulator<std::int32_t>{array, operation, identity, terminator},
155 "REDUCE");
156}
157void RTDEF(ReduceInteger4Dim)(Descriptor &result, const Descriptor &array,
158 ReductionOperation<std::int32_t> operation, const char *source, int line,
159 int dim, const Descriptor *mask, const std::int32_t *identity,
160 bool ordered) {
161 Terminator terminator{source, line};
162 using Accumulator = ReduceAccumulator<std::int32_t>;
163 Accumulator accumulator{array, operation, identity, terminator};
164 PartialReduction<Accumulator, TypeCategory::Integer, 4>(result, array,
165 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
166}
167std::int64_t RTDEF(ReduceInteger8)(const Descriptor &array,
168 ReductionOperation<std::int64_t> operation, const char *source, int line,
169 int dim, const Descriptor *mask, const std::int64_t *identity,
170 bool ordered) {
171 Terminator terminator{source, line};
172 return GetTotalReduction<TypeCategory::Integer, 8>(array, source, line, dim,
173 mask,
174 ReduceAccumulator<std::int64_t>{array, operation, identity, terminator},
175 "REDUCE");
176}
177void RTDEF(ReduceInteger8Dim)(Descriptor &result, const Descriptor &array,
178 ReductionOperation<std::int64_t> operation, const char *source, int line,
179 int dim, const Descriptor *mask, const std::int64_t *identity,
180 bool ordered) {
181 Terminator terminator{source, line};
182 using Accumulator = ReduceAccumulator<std::int64_t>;
183 Accumulator accumulator{array, operation, identity, terminator};
184 PartialReduction<Accumulator, TypeCategory::Integer, 8>(result, array,
185 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
186}
187#ifdef __SIZEOF_INT128__
188common::int128_t RTDEF(ReduceInteger16)(const Descriptor &array,
189 ReductionOperation<common::int128_t> operation, const char *source,
190 int line, int dim, const Descriptor *mask, const common::int128_t *identity,
191 bool ordered) {
192 Terminator terminator{source, line};
193 return GetTotalReduction<TypeCategory::Integer, 16>(array, source, line, dim,
194 mask,
195 ReduceAccumulator<common::int128_t>{
196 array, operation, identity, terminator},
197 "REDUCE");
198}
199void RTDEF(ReduceInteger16Dim)(Descriptor &result, const Descriptor &array,
200 ReductionOperation<common::int128_t> operation, const char *source,
201 int line, int dim, const Descriptor *mask, const common::int128_t *identity,
202 bool ordered) {
203 Terminator terminator{source, line};
204 using Accumulator = ReduceAccumulator<common::int128_t>;
205 Accumulator accumulator{array, operation, identity, terminator};
206 PartialReduction<Accumulator, TypeCategory::Integer, 16>(result, array,
207 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
208}
209#endif
210
211// TODO: real/complex(2 & 3)
212float RTDEF(ReduceReal4)(const Descriptor &array,
213 ReductionOperation<float> operation, const char *source, int line, int dim,
214 const Descriptor *mask, const float *identity, bool ordered) {
215 Terminator terminator{source, line};
216 return GetTotalReduction<TypeCategory::Real, 4>(array, source, line, dim,
217 mask, ReduceAccumulator<float>{array, operation, identity, terminator},
218 "REDUCE");
219}
220void RTDEF(ReduceReal4Dim)(Descriptor &result, const Descriptor &array,
221 ReductionOperation<float> operation, const char *source, int line, int dim,
222 const Descriptor *mask, const float *identity, bool ordered) {
223 Terminator terminator{source, line};
224 using Accumulator = ReduceAccumulator<float>;
225 Accumulator accumulator{array, operation, identity, terminator};
226 PartialReduction<Accumulator, TypeCategory::Real, 4>(result, array,
227 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
228}
229double RTDEF(ReduceReal8)(const Descriptor &array,
230 ReductionOperation<double> operation, const char *source, int line, int dim,
231 const Descriptor *mask, const double *identity, bool ordered) {
232 Terminator terminator{source, line};
233 return GetTotalReduction<TypeCategory::Real, 8>(array, source, line, dim,
234 mask, ReduceAccumulator<double>{array, operation, identity, terminator},
235 "REDUCE");
236}
237void RTDEF(ReduceReal8Dim)(Descriptor &result, const Descriptor &array,
238 ReductionOperation<double> operation, const char *source, int line, int dim,
239 const Descriptor *mask, const double *identity, bool ordered) {
240 Terminator terminator{source, line};
241 using Accumulator = ReduceAccumulator<double>;
242 Accumulator accumulator{array, operation, identity, terminator};
243 PartialReduction<Accumulator, TypeCategory::Real, 8>(result, array,
244 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
245}
246#if LDBL_MANT_DIG == 64
247long double RTDEF(ReduceReal10)(const Descriptor &array,
248 ReductionOperation<long double> operation, const char *source, int line,
249 int dim, const Descriptor *mask, const long double *identity,
250 bool ordered) {
251 Terminator terminator{source, line};
252 return GetTotalReduction<TypeCategory::Real, 10>(array, source, line, dim,
253 mask,
254 ReduceAccumulator<long double>{array, operation, identity, terminator},
255 "REDUCE");
256}
257void RTDEF(ReduceReal10Dim)(Descriptor &result, const Descriptor &array,
258 ReductionOperation<long double> operation, const char *source, int line,
259 int dim, const Descriptor *mask, const long double *identity,
260 bool ordered) {
261 Terminator terminator{source, line};
262 using Accumulator = ReduceAccumulator<long double>;
263 Accumulator accumulator{array, operation, identity, terminator};
264 PartialReduction<Accumulator, TypeCategory::Real, 10>(result, array,
265 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
266}
267#endif
268#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
269CppFloat128Type RTDEF(ReduceReal16)(const Descriptor &array,
270 ReductionOperation<CppFloat128Type> operation, const char *source, int line,
271 int dim, const Descriptor *mask, const CppFloat128Type *identity,
272 bool ordered) {
273 Terminator terminator{source, line};
274 return GetTotalReduction<TypeCategory::Real, 16>(array, source, line, dim,
275 mask,
276 ReduceAccumulator<CppFloat128Type>{
277 array, operation, identity, terminator},
278 "REDUCE");
279}
280void RTDEF(ReduceReal16Dim)(Descriptor &result, const Descriptor &array,
281 ReductionOperation<CppFloat128Type> operation, const char *source, int line,
282 int dim, const Descriptor *mask, const CppFloat128Type *identity,
283 bool ordered) {
284 Terminator terminator{source, line};
285 using Accumulator = ReduceAccumulator<CppFloat128Type>;
286 Accumulator accumulator{array, operation, identity, terminator};
287 PartialReduction<Accumulator, TypeCategory::Real, 16>(result, array,
288 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
289}
290#endif
291
292void RTDEF(CppReduceComplex4)(std::complex<float> &result,
293 const Descriptor &array, ReductionOperation<std::complex<float>> operation,
294 const char *source, int line, int dim, const Descriptor *mask,
295 const std::complex<float> *identity, bool ordered) {
296 Terminator terminator{source, line};
297 result = GetTotalReduction<TypeCategory::Complex, 4>(array, source, line, dim,
298 mask,
299 ReduceAccumulator<std::complex<float>>{
300 array, operation, identity, terminator},
301 "REDUCE");
302}
303void RTDEF(CppReduceComplex4Dim)(Descriptor &result, const Descriptor &array,
304 ReductionOperation<std::complex<float>> operation, const char *source,
305 int line, int dim, const Descriptor *mask,
306 const std::complex<float> *identity, bool ordered) {
307 Terminator terminator{source, line};
308 using Accumulator = ReduceAccumulator<std::complex<float>>;
309 Accumulator accumulator{array, operation, identity, terminator};
310 PartialReduction<Accumulator, TypeCategory::Complex, 4>(result, array,
311 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
312}
313void RTDEF(CppReduceComplex8)(std::complex<double> &result,
314 const Descriptor &array, ReductionOperation<std::complex<double>> operation,
315 const char *source, int line, int dim, const Descriptor *mask,
316 const std::complex<double> *identity, bool ordered) {
317 Terminator terminator{source, line};
318 result = GetTotalReduction<TypeCategory::Complex, 8>(array, source, line, dim,
319 mask,
320 ReduceAccumulator<std::complex<double>>{
321 array, operation, identity, terminator},
322 "REDUCE");
323}
324void RTDEF(CppReduceComplex8Dim)(Descriptor &result, const Descriptor &array,
325 ReductionOperation<std::complex<double>> operation, const char *source,
326 int line, int dim, const Descriptor *mask,
327 const std::complex<double> *identity, bool ordered) {
328 Terminator terminator{source, line};
329 using Accumulator = ReduceAccumulator<std::complex<double>>;
330 Accumulator accumulator{array, operation, identity, terminator};
331 PartialReduction<Accumulator, TypeCategory::Complex, 8>(result, array,
332 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
333}
334#if LDBL_MANT_DIG == 64
335void RTDEF(CppReduceComplex10)(std::complex<long double> &result,
336 const Descriptor &array,
337 ReductionOperation<std::complex<long double>> operation, const char *source,
338 int line, int dim, const Descriptor *mask,
339 const std::complex<long double> *identity, bool ordered) {
340 Terminator terminator{source, line};
341 result = GetTotalReduction<TypeCategory::Complex, 10>(array, source, line,
342 dim, mask,
343 ReduceAccumulator<std::complex<long double>>{
344 array, operation, identity, terminator},
345 "REDUCE");
346}
347void RTDEF(CppReduceComplex10Dim)(Descriptor &result, const Descriptor &array,
348 ReductionOperation<std::complex<long double>> operation, const char *source,
349 int line, int dim, const Descriptor *mask,
350 const std::complex<long double> *identity, bool ordered) {
351 Terminator terminator{source, line};
352 using Accumulator = ReduceAccumulator<std::complex<long double>>;
353 Accumulator accumulator{array, operation, identity, terminator};
354 PartialReduction<Accumulator, TypeCategory::Complex, 10>(result, array,
355 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
356}
357#endif
358#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
359void RTDEF(CppReduceComplex16)(std::complex<CppFloat128Type> &result,
360 const Descriptor &array,
361 ReductionOperation<std::complex<CppFloat128Type>> operation,
362 const char *source, int line, int dim, const Descriptor *mask,
363 const std::complex<CppFloat128Type> *identity, bool ordered) {
364 Terminator terminator{source, line};
365 result = GetTotalReduction<TypeCategory::Complex, 16>(array, source, line,
366 dim, mask,
367 ReduceAccumulator<std::complex<CppFloat128Type>>{
368 array, operation, identity, terminator},
369 "REDUCE");
370}
371void RTDEF(CppReduceComplex16Dim)(Descriptor &result, const Descriptor &array,
372 ReductionOperation<std::complex<CppFloat128Type>> operation,
373 const char *source, int line, int dim, const Descriptor *mask,
374 const std::complex<CppFloat128Type> *identity, bool ordered) {
375 Terminator terminator{source, line};
376 using Accumulator = ReduceAccumulator<std::complex<CppFloat128Type>>;
377 Accumulator accumulator{array, operation, identity, terminator};
378 PartialReduction<Accumulator, TypeCategory::Complex, 16>(result, array,
379 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
380}
381#endif
382
383bool RTDEF(ReduceLogical1)(const Descriptor &array,
384 ReductionOperation<std::int8_t> operation, const char *source, int line,
385 int dim, const Descriptor *mask, const std::int8_t *identity,
386 bool ordered) {
387 return RTNAME(ReduceInteger1)(
388 array, operation, source, line, dim, mask, identity, ordered) != 0;
389}
390void RTDEF(ReduceLogical1Dim)(Descriptor &result, const Descriptor &array,
391 ReductionOperation<std::int8_t> operation, const char *source, int line,
392 int dim, const Descriptor *mask, const std::int8_t *identity,
393 bool ordered) {
394 RTNAME(ReduceInteger1Dim)
395 (result, array, operation, source, line, dim, mask, identity, ordered);
396}
397bool RTDEF(ReduceLogical2)(const Descriptor &array,
398 ReductionOperation<std::int16_t> operation, const char *source, int line,
399 int dim, const Descriptor *mask, const std::int16_t *identity,
400 bool ordered) {
401 return RTNAME(ReduceInteger2)(
402 array, operation, source, line, dim, mask, identity, ordered) != 0;
403}
404void RTDEF(ReduceLogical2Dim)(Descriptor &result, const Descriptor &array,
405 ReductionOperation<std::int16_t> operation, const char *source, int line,
406 int dim, const Descriptor *mask, const std::int16_t *identity,
407 bool ordered) {
408 RTNAME(ReduceInteger2Dim)
409 (result, array, operation, source, line, dim, mask, identity, ordered);
410}
411bool RTDEF(ReduceLogical4)(const Descriptor &array,
412 ReductionOperation<std::int32_t> operation, const char *source, int line,
413 int dim, const Descriptor *mask, const std::int32_t *identity,
414 bool ordered) {
415 return RTNAME(ReduceInteger4)(
416 array, operation, source, line, dim, mask, identity, ordered) != 0;
417}
418void RTDEF(ReduceLogical4Dim)(Descriptor &result, const Descriptor &array,
419 ReductionOperation<std::int32_t> operation, const char *source, int line,
420 int dim, const Descriptor *mask, const std::int32_t *identity,
421 bool ordered) {
422 RTNAME(ReduceInteger4Dim)
423 (result, array, operation, source, line, dim, mask, identity, ordered);
424}
425bool RTDEF(ReduceLogical8)(const Descriptor &array,
426 ReductionOperation<std::int64_t> operation, const char *source, int line,
427 int dim, const Descriptor *mask, const std::int64_t *identity,
428 bool ordered) {
429 return RTNAME(ReduceInteger8)(
430 array, operation, source, line, dim, mask, identity, ordered) != 0;
431}
432void RTDEF(ReduceLogical8Dim)(Descriptor &result, const Descriptor &array,
433 ReductionOperation<std::int64_t> operation, const char *source, int line,
434 int dim, const Descriptor *mask, const std::int64_t *identity,
435 bool ordered) {
436 RTNAME(ReduceInteger8Dim)
437 (result, array, operation, source, line, dim, mask, identity, ordered);
438}
439
440void RTDEF(ReduceChar1)(char *result, const Descriptor &array,
441 ReductionCharOperation<char> operation, const char *source, int line,
442 int dim, const Descriptor *mask, const char *identity, bool ordered) {
443 Terminator terminator{source, line};
444 BufferedReduceAccumulator<char, ReductionCharOperation<char>,
445 /*hasLength=*/true>
446 accumulator{array, operation, identity, terminator};
447 DoTotalReduction<char>(array, dim, mask, accumulator, "REDUCE", terminator);
448 accumulator.GetResult(result);
449}
450void RTDEF(ReduceCharacter1Dim)(Descriptor &result, const Descriptor &array,
451 ReductionCharOperation<char> operation, const char *source, int line,
452 int dim, const Descriptor *mask, const char *identity, bool ordered) {
453 Terminator terminator{source, line};
454 using Accumulator = BufferedReduceAccumulator<char,
455 ReductionCharOperation<char>, /*hasLength=*/true>;
456 Accumulator accumulator{array, operation, identity, terminator};
457 PartialReduction<Accumulator, TypeCategory::Character, 1>(result, array,
458 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
459}
460void RTDEF(ReduceChar2)(char16_t *result, const Descriptor &array,
461 ReductionCharOperation<char16_t> operation, const char *source, int line,
462 int dim, const Descriptor *mask, const char16_t *identity, bool ordered) {
463 Terminator terminator{source, line};
464 BufferedReduceAccumulator<char16_t, ReductionCharOperation<char16_t>,
465 /*hasLength=*/true>
466 accumulator{array, operation, identity, terminator};
467 DoTotalReduction<char16_t>(
468 array, dim, mask, accumulator, "REDUCE", terminator);
469 accumulator.GetResult(result);
470}
471void RTDEF(ReduceCharacter2Dim)(Descriptor &result, const Descriptor &array,
472 ReductionCharOperation<char16_t> operation, const char *source, int line,
473 int dim, const Descriptor *mask, const char16_t *identity, bool ordered) {
474 Terminator terminator{source, line};
475 using Accumulator = BufferedReduceAccumulator<char16_t,
476 ReductionCharOperation<char16_t>, /*hasLength=*/true>;
477 Accumulator accumulator{array, operation, identity, terminator};
478 PartialReduction<Accumulator, TypeCategory::Character, 2>(result, array,
479 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
480}
481void RTDEF(ReduceChar4)(char32_t *result, const Descriptor &array,
482 ReductionCharOperation<char32_t> operation, const char *source, int line,
483 int dim, const Descriptor *mask, const char32_t *identity, bool ordered) {
484 Terminator terminator{source, line};
485 BufferedReduceAccumulator<char32_t, ReductionCharOperation<char32_t>,
486 /*hasLength=*/true>
487 accumulator{array, operation, identity, terminator};
488 DoTotalReduction<char32_t>(
489 array, dim, mask, accumulator, "REDUCE", terminator);
490 accumulator.GetResult(result);
491}
492void RTDEF(ReduceCharacter4Dim)(Descriptor &result, const Descriptor &array,
493 ReductionCharOperation<char32_t> operation, const char *source, int line,
494 int dim, const Descriptor *mask, const char32_t *identity, bool ordered) {
495 Terminator terminator{source, line};
496 using Accumulator = BufferedReduceAccumulator<char32_t,
497 ReductionCharOperation<char32_t>, /*hasLength=*/true>;
498 Accumulator accumulator{array, operation, identity, terminator};
499 PartialReduction<Accumulator, TypeCategory::Character, 4>(result, array,
500 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
501}
502
503void RTDEF(ReduceDerivedType)(char *result, const Descriptor &array,
504 ReductionDerivedTypeOperation operation, const char *source, int line,
505 int dim, const Descriptor *mask, const char *identity, bool ordered) {
506 Terminator terminator{source, line};
507 BufferedReduceAccumulator<char, ReductionDerivedTypeOperation,
508 /*hasLength=*/false>
509 accumulator{array, operation, identity, terminator};
510 DoTotalReduction<char>(array, dim, mask, accumulator, "REDUCE", terminator);
511 accumulator.GetResult(result);
512}
513void RTDEF(ReduceDerivedTypeDim)(Descriptor &result, const Descriptor &array,
514 ReductionDerivedTypeOperation operation, const char *source, int line,
515 int dim, const Descriptor *mask, const char *identity, bool ordered) {
516 Terminator terminator{source, line};
517 using Accumulator = BufferedReduceAccumulator<char,
518 ReductionDerivedTypeOperation, /*hasLength=*/false>;
519 Accumulator accumulator{array, operation, identity, terminator};
520 PartialReduction<Accumulator, TypeCategory::Derived, 0>(result, array,
521 array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator);
522}
523
524RT_EXT_API_GROUP_END
525} // extern "C"
526} // namespace Fortran::runtime
527

source code of flang/runtime/reduce.cpp