1 //===-- runtime/product.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 // Implements PRODUCT for all required operand types and shapes. 10 11 #include "reduction-templates.h" 12 #include "flang/Common/float128.h" 13 #include "flang/Runtime/reduction.h" 14 #include <cfloat> 15 #include <cinttypes> 16 #include <complex> 17 18 namespace Fortran::runtime { 19 template <typename INTERMEDIATE> class NonComplexProductAccumulator { 20 public: 21 explicit RT_API_ATTRS NonComplexProductAccumulator(const Descriptor &array) 22 : array_{array} {} 23 RT_API_ATTRS void Reinitialize() { product_ = 1; } 24 template <typename A> 25 RT_API_ATTRS void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { 26 *p = static_cast<A>(product_); 27 } 28 template <typename A> 29 RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { 30 product_ *= *array_.Element<A>(at); 31 return product_ != 0; 32 } 33 34 private: 35 const Descriptor &array_; 36 INTERMEDIATE product_{1}; 37 }; 38 39 template <typename PART> class ComplexProductAccumulator { 40 public: 41 explicit RT_API_ATTRS ComplexProductAccumulator(const Descriptor &array) 42 : array_{array} {} 43 RT_API_ATTRS void Reinitialize() { product_ = rtcmplx::complex<PART>{1, 0}; } 44 template <typename A> 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())}; 49 } 50 template <typename A> 51 RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { 52 product_ *= *array_.Element<A>(at); 53 return true; 54 } 55 56 private: 57 const Descriptor &array_; 58 rtcmplx::complex<PART> product_{1, 0}; 59 }; 60 61 extern "C" { 62 RT_EXT_API_GROUP_BEGIN 63 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}, 68 "PRODUCT"); 69 } 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}, 74 "PRODUCT"); 75 } 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}, 80 "PRODUCT"); 81 } 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}, 86 "PRODUCT"); 87 } 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, 93 mask, 94 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Integer, 16>>{x}, 95 "PRODUCT"); 96 } 97 #endif 98 99 CppTypeFor<TypeCategory::Unsigned, 1> RTDEF(ProductUnsigned1)( 100 const Descriptor &x, const char *source, int line, int dim, 101 const Descriptor *mask) { 102 return GetTotalReduction<TypeCategory::Unsigned, 1>(x, source, line, dim, 103 mask, 104 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Unsigned, 4>>{x}, 105 "PRODUCT"); 106 } 107 CppTypeFor<TypeCategory::Unsigned, 2> RTDEF(ProductUnsigned2)( 108 const Descriptor &x, const char *source, int line, int dim, 109 const Descriptor *mask) { 110 return GetTotalReduction<TypeCategory::Unsigned, 2>(x, source, line, dim, 111 mask, 112 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Unsigned, 4>>{x}, 113 "PRODUCT"); 114 } 115 CppTypeFor<TypeCategory::Unsigned, 4> RTDEF(ProductUnsigned4)( 116 const Descriptor &x, const char *source, int line, int dim, 117 const Descriptor *mask) { 118 return GetTotalReduction<TypeCategory::Unsigned, 4>(x, source, line, dim, 119 mask, 120 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Unsigned, 4>>{x}, 121 "PRODUCT"); 122 } 123 CppTypeFor<TypeCategory::Unsigned, 8> RTDEF(ProductUnsigned8)( 124 const Descriptor &x, const char *source, int line, int dim, 125 const Descriptor *mask) { 126 return GetTotalReduction<TypeCategory::Unsigned, 8>(x, source, line, dim, 127 mask, 128 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Unsigned, 8>>{x}, 129 "PRODUCT"); 130 } 131 #ifdef __SIZEOF_INT128__ 132 CppTypeFor<TypeCategory::Unsigned, 16> RTDEF(ProductUnsigned16)( 133 const Descriptor &x, const char *source, int line, int dim, 134 const Descriptor *mask) { 135 return GetTotalReduction<TypeCategory::Unsigned, 16>(x, source, line, dim, 136 mask, 137 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Unsigned, 16>>{x}, 138 "PRODUCT"); 139 } 140 #endif 141 142 // TODO: real/complex(2 & 3) 143 CppTypeFor<TypeCategory::Real, 4> RTDEF(ProductReal4)(const Descriptor &x, 144 const char *source, int line, int dim, const Descriptor *mask) { 145 return GetTotalReduction<TypeCategory::Real, 4>(x, source, line, dim, mask, 146 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 4>>{x}, 147 "PRODUCT"); 148 } 149 CppTypeFor<TypeCategory::Real, 8> RTDEF(ProductReal8)(const Descriptor &x, 150 const char *source, int line, int dim, const Descriptor *mask) { 151 return GetTotalReduction<TypeCategory::Real, 8>(x, source, line, dim, mask, 152 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 8>>{x}, 153 "PRODUCT"); 154 } 155 #if HAS_FLOAT80 156 CppTypeFor<TypeCategory::Real, 10> RTDEF(ProductReal10)(const Descriptor &x, 157 const char *source, int line, int dim, const Descriptor *mask) { 158 return GetTotalReduction<TypeCategory::Real, 10>(x, source, line, dim, mask, 159 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 10>>{x}, 160 "PRODUCT"); 161 } 162 #endif 163 #if HAS_LDBL128 || HAS_FLOAT128 164 CppTypeFor<TypeCategory::Real, 16> RTDEF(ProductReal16)(const Descriptor &x, 165 const char *source, int line, int dim, const Descriptor *mask) { 166 return GetTotalReduction<TypeCategory::Real, 16>(x, source, line, dim, mask, 167 NonComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 16>>{x}, 168 "PRODUCT"); 169 } 170 #endif 171 172 void RTDEF(CppProductComplex4)(CppTypeFor<TypeCategory::Complex, 4> &result, 173 const Descriptor &x, const char *source, int line, int dim, 174 const Descriptor *mask) { 175 result = GetTotalReduction<TypeCategory::Complex, 4>(x, source, line, dim, 176 mask, ComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 4>>{x}, 177 "PRODUCT"); 178 } 179 void RTDEF(CppProductComplex8)(CppTypeFor<TypeCategory::Complex, 8> &result, 180 const Descriptor &x, const char *source, int line, int dim, 181 const Descriptor *mask) { 182 result = GetTotalReduction<TypeCategory::Complex, 8>(x, source, line, dim, 183 mask, ComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 8>>{x}, 184 "PRODUCT"); 185 } 186 #if HAS_FLOAT80 187 void RTDEF(CppProductComplex10)(CppTypeFor<TypeCategory::Complex, 10> &result, 188 const Descriptor &x, const char *source, int line, int dim, 189 const Descriptor *mask) { 190 result = GetTotalReduction<TypeCategory::Complex, 10>(x, source, line, dim, 191 mask, ComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 10>>{x}, 192 "PRODUCT"); 193 } 194 #endif 195 #if HAS_LDBL128 || HAS_FLOAT128 196 void RTDEF(CppProductComplex16)(CppTypeFor<TypeCategory::Complex, 16> &result, 197 const Descriptor &x, const char *source, int line, int dim, 198 const Descriptor *mask) { 199 result = GetTotalReduction<TypeCategory::Complex, 16>(x, source, line, dim, 200 mask, ComplexProductAccumulator<CppTypeFor<TypeCategory::Real, 16>>{x}, 201 "PRODUCT"); 202 } 203 #endif 204 205 void RTDEF(ProductDim)(Descriptor &result, const Descriptor &x, int dim, 206 const char *source, int line, const Descriptor *mask) { 207 TypedPartialNumericReduction<NonComplexProductAccumulator, 208 NonComplexProductAccumulator, ComplexProductAccumulator, 209 /*MIN_REAL_KIND=*/4>(result, x, dim, source, line, mask, "PRODUCT"); 210 } 211 212 RT_EXT_API_GROUP_END 213 } // extern "C" 214 } // namespace Fortran::runtime 215