//===-- runtime/product.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Implements PRODUCT for all required operand types and shapes. #include "reduction-templates.h" #include "flang/Runtime/float128.h" #include "flang/Runtime/reduction.h" #include #include #include namespace Fortran::runtime { template class NonComplexProductAccumulator { public: explicit NonComplexProductAccumulator(const Descriptor &array) : array_{array} {} void Reinitialize() { product_ = 1; } template void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { *p = static_cast(product_); } template bool AccumulateAt(const SubscriptValue at[]) { product_ *= *array_.Element(at); return product_ != 0; } private: const Descriptor &array_; INTERMEDIATE product_{1}; }; template class ComplexProductAccumulator { public: explicit ComplexProductAccumulator(const Descriptor &array) : array_{array} {} void Reinitialize() { product_ = std::complex{1, 0}; } template void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { using ResultPart = typename A::value_type; *p = {static_cast(product_.real()), static_cast(product_.imag())}; } template bool AccumulateAt(const SubscriptValue at[]) { product_ *= *array_.Element(at); return true; } private: const Descriptor &array_; std::complex product_{1, 0}; }; extern "C" { CppTypeFor RTNAME(ProductInteger1)( const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } CppTypeFor RTNAME(ProductInteger2)( const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } CppTypeFor RTNAME(ProductInteger4)( const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } CppTypeFor RTNAME(ProductInteger8)( const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } #ifdef __SIZEOF_INT128__ CppTypeFor RTNAME(ProductInteger16)( const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } #endif // TODO: real/complex(2 & 3) CppTypeFor RTNAME(ProductReal4)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } CppTypeFor RTNAME(ProductReal8)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } #if LDBL_MANT_DIG == 64 CppTypeFor RTNAME(ProductReal10)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } #elif LDBL_MANT_DIG == 113 CppTypeFor RTNAME(ProductReal16)(const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { return GetTotalReduction(x, source, line, dim, mask, NonComplexProductAccumulator>{x}, "PRODUCT"); } #endif void RTNAME(CppProductComplex4)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { result = GetTotalReduction(x, source, line, dim, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } void RTNAME(CppProductComplex8)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { result = GetTotalReduction(x, source, line, dim, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } #if LDBL_MANT_DIG == 64 void RTNAME(CppProductComplex10)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { result = GetTotalReduction(x, source, line, dim, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } #elif LDBL_MANT_DIG == 113 void RTNAME(CppProductComplex16)(CppTypeFor &result, const Descriptor &x, const char *source, int line, int dim, const Descriptor *mask) { result = GetTotalReduction(x, source, line, dim, mask, ComplexProductAccumulator>{x}, "PRODUCT"); } #endif void RTNAME(ProductDim)(Descriptor &result, const Descriptor &x, int dim, const char *source, int line, const Descriptor *mask) { TypedPartialNumericReduction( result, x, dim, source, line, mask, "PRODUCT"); } } // extern "C" } // namespace Fortran::runtime