1 //===-- runtime/product.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implements PRODUCT for all required operand types and shapes.
11 #include "reduction-templates.h"
12 #include "flang/Common/float128.h"
13 #include "flang/Runtime/reduction.h"
18 namespace Fortran::runtime
{
19 template <typename INTERMEDIATE
> class NonComplexProductAccumulator
{
21 explicit RT_API_ATTRS
NonComplexProductAccumulator(const Descriptor
&array
)
23 RT_API_ATTRS
void Reinitialize() { product_
= 1; }
25 RT_API_ATTRS
void GetResult(A
*p
, int /*zeroBasedDim*/ = -1) const {
26 *p
= static_cast<A
>(product_
);
29 RT_API_ATTRS
bool AccumulateAt(const SubscriptValue at
[]) {
30 product_
*= *array_
.Element
<A
>(at
);
35 const Descriptor
&array_
;
36 INTERMEDIATE product_
{1};
39 template <typename PART
> class ComplexProductAccumulator
{
41 explicit RT_API_ATTRS
ComplexProductAccumulator(const Descriptor
&array
)
43 RT_API_ATTRS
void Reinitialize() { product_
= rtcmplx::complex<PART
>{1, 0}; }
45 RT_API_ATTRS
void GetResult(A
*p
, int /*zeroBasedDim*/ = -1) const {
46 using ResultPart
= typename
A::value_type
;
47 *p
= {static_cast<ResultPart
>(product_
.real()),
48 static_cast<ResultPart
>(product_
.imag())};
51 RT_API_ATTRS
bool AccumulateAt(const SubscriptValue at
[]) {
52 product_
*= *array_
.Element
<A
>(at
);
57 const Descriptor
&array_
;
58 rtcmplx::complex<PART
> product_
{1, 0};
62 RT_EXT_API_GROUP_BEGIN
64 CppTypeFor
<TypeCategory::Integer
, 1> RTDEF(ProductInteger1
)(const Descriptor
&x
,
65 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
66 return GetTotalReduction
<TypeCategory::Integer
, 1>(x
, source
, line
, dim
, mask
,
67 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Integer
, 4>>{x
},
70 CppTypeFor
<TypeCategory::Integer
, 2> RTDEF(ProductInteger2
)(const Descriptor
&x
,
71 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
72 return GetTotalReduction
<TypeCategory::Integer
, 2>(x
, source
, line
, dim
, mask
,
73 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Integer
, 4>>{x
},
76 CppTypeFor
<TypeCategory::Integer
, 4> RTDEF(ProductInteger4
)(const Descriptor
&x
,
77 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
78 return GetTotalReduction
<TypeCategory::Integer
, 4>(x
, source
, line
, dim
, mask
,
79 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Integer
, 4>>{x
},
82 CppTypeFor
<TypeCategory::Integer
, 8> RTDEF(ProductInteger8
)(const Descriptor
&x
,
83 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
84 return GetTotalReduction
<TypeCategory::Integer
, 8>(x
, source
, line
, dim
, mask
,
85 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Integer
, 8>>{x
},
88 #ifdef __SIZEOF_INT128__
89 CppTypeFor
<TypeCategory::Integer
, 16> RTDEF(ProductInteger16
)(
90 const Descriptor
&x
, const char *source
, int line
, int dim
,
91 const Descriptor
*mask
) {
92 return GetTotalReduction
<TypeCategory::Integer
, 16>(x
, source
, line
, dim
,
94 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Integer
, 16>>{x
},
99 // TODO: real/complex(2 & 3)
100 CppTypeFor
<TypeCategory::Real
, 4> RTDEF(ProductReal4
)(const Descriptor
&x
,
101 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
102 return GetTotalReduction
<TypeCategory::Real
, 4>(x
, source
, line
, dim
, mask
,
103 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 4>>{x
},
106 CppTypeFor
<TypeCategory::Real
, 8> RTDEF(ProductReal8
)(const Descriptor
&x
,
107 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
108 return GetTotalReduction
<TypeCategory::Real
, 8>(x
, source
, line
, dim
, mask
,
109 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 8>>{x
},
113 CppTypeFor
<TypeCategory::Real
, 10> RTDEF(ProductReal10
)(const Descriptor
&x
,
114 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
115 return GetTotalReduction
<TypeCategory::Real
, 10>(x
, source
, line
, dim
, mask
,
116 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 10>>{x
},
120 #if HAS_LDBL128 || HAS_FLOAT128
121 CppTypeFor
<TypeCategory::Real
, 16> RTDEF(ProductReal16
)(const Descriptor
&x
,
122 const char *source
, int line
, int dim
, const Descriptor
*mask
) {
123 return GetTotalReduction
<TypeCategory::Real
, 16>(x
, source
, line
, dim
, mask
,
124 NonComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 16>>{x
},
129 void RTDEF(CppProductComplex4
)(CppTypeFor
<TypeCategory::Complex
, 4> &result
,
130 const Descriptor
&x
, const char *source
, int line
, int dim
,
131 const Descriptor
*mask
) {
132 result
= GetTotalReduction
<TypeCategory::Complex
, 4>(x
, source
, line
, dim
,
133 mask
, ComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 4>>{x
},
136 void RTDEF(CppProductComplex8
)(CppTypeFor
<TypeCategory::Complex
, 8> &result
,
137 const Descriptor
&x
, const char *source
, int line
, int dim
,
138 const Descriptor
*mask
) {
139 result
= GetTotalReduction
<TypeCategory::Complex
, 8>(x
, source
, line
, dim
,
140 mask
, ComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 8>>{x
},
144 void RTDEF(CppProductComplex10
)(CppTypeFor
<TypeCategory::Complex
, 10> &result
,
145 const Descriptor
&x
, const char *source
, int line
, int dim
,
146 const Descriptor
*mask
) {
147 result
= GetTotalReduction
<TypeCategory::Complex
, 10>(x
, source
, line
, dim
,
148 mask
, ComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 10>>{x
},
152 #if HAS_LDBL128 || HAS_FLOAT128
153 void RTDEF(CppProductComplex16
)(CppTypeFor
<TypeCategory::Complex
, 16> &result
,
154 const Descriptor
&x
, const char *source
, int line
, int dim
,
155 const Descriptor
*mask
) {
156 result
= GetTotalReduction
<TypeCategory::Complex
, 16>(x
, source
, line
, dim
,
157 mask
, ComplexProductAccumulator
<CppTypeFor
<TypeCategory::Real
, 16>>{x
},
162 void RTDEF(ProductDim
)(Descriptor
&result
, const Descriptor
&x
, int dim
,
163 const char *source
, int line
, const Descriptor
*mask
) {
164 TypedPartialNumericReduction
<NonComplexProductAccumulator
,
165 NonComplexProductAccumulator
, ComplexProductAccumulator
,
166 /*MIN_REAL_KIND=*/4>(result
, x
, dim
, source
, line
, mask
, "PRODUCT");
171 } // namespace Fortran::runtime