/*===-- lib/flang_rt/complex-reduction.c ----------------------------*- C -*-=== * * 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 * *===----------------------------------------------------------------------===*/ #include "complex-reduction.h" #include struct CppComplexFloat { float r, i; }; struct CppComplexDouble { double r, i; }; struct CppComplexLongDouble { long double r, i; }; #if HAS_LDBL128 || HAS_FLOAT128 struct CppComplexFloat128 { CFloat128Type r, i; }; #endif /* Not all environments define CMPLXF, CMPLX, CMPLXL. */ #ifndef CMPLXF #if defined(__clang_major__) && (__clang_major__ >= 12) #define CMPLXF __builtin_complex #else static float_Complex_t CMPLXF(float r, float i) { union { struct CppComplexFloat x; float_Complex_t result; } u; u.x.r = r; u.x.i = i; return u.result; } #endif #endif #ifndef CMPLX #if defined(__clang_major__) && (__clang_major__ >= 12) #define CMPLX __builtin_complex #else static double_Complex_t CMPLX(double r, double i) { union { struct CppComplexDouble x; double_Complex_t result; } u; u.x.r = r; u.x.i = i; return u.result; } #endif #endif #ifndef CMPLXL #if defined(__clang_major__) && (__clang_major__ >= 12) #define CMPLXL __builtin_complex #else static long_double_Complex_t CMPLXL(long double r, long double i) { union { struct CppComplexLongDouble x; long_double_Complex_t result; } u; u.x.r = r; u.x.i = i; return u.result; } #endif #endif #if HAS_LDBL128 || HAS_FLOAT128 #ifndef CMPLXF128 /* * GCC 7.4.0 (currently minimum GCC version for llvm builds) * supports __builtin_complex. For Clang, require >=12.0. * Otherwise, rely on the memory layout compatibility. */ #if (defined(__clang_major__) && (__clang_major__ >= 12)) || \ (defined(__GNUC__) && !defined(__clang__)) #define CMPLXF128 __builtin_complex #else static CFloat128ComplexType CMPLXF128(CFloat128Type r, CFloat128Type i) { union { struct CppComplexFloat128 x; CFloat128ComplexType result; } u; u.x.r = r; u.x.i = i; return u.result; } #endif #endif #endif /* RTNAME(SumComplex4) calls RTNAME(CppSumComplex4) with the same arguments * and converts the members of its C++ complex result to C _Complex. */ #define CPP_NAME(name) Cpp##name #define ADAPT_REDUCTION(name, cComplex, cpptype, cmplxMacro, ARGS, ARG_NAMES) \ struct cpptype RTNAME(CPP_NAME(name))(struct cpptype *, ARGS); \ cComplex RTNAME(name)(ARGS) { \ struct cpptype result; \ RTNAME(CPP_NAME(name))(&result, ARG_NAMES); \ return cmplxMacro(result.r, result.i); \ } /* TODO: COMPLEX(2 & 3) */ /* SUM() */ ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF, REDUCTION_ARGS, REDUCTION_ARG_NAMES) ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #if HAS_FLOAT80 ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif #if HAS_LDBL128 || HAS_FLOAT128 ADAPT_REDUCTION(SumComplex16, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif /* PRODUCT() */ ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, REDUCTION_ARGS, REDUCTION_ARG_NAMES) ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #if HAS_FLOAT80 ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif #if HAS_LDBL128 || HAS_FLOAT128 ADAPT_REDUCTION(ProductComplex16, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES) #endif /* DOT_PRODUCT() */ ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) #if HAS_FLOAT80 ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) #endif #if HAS_LDBL128 || HAS_FLOAT128 ADAPT_REDUCTION(DotProductComplex16, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) #endif /* REDUCE() */ #define RARGS REDUCE_ARGS(float_Complex_t, float_Complex_t_ref_op) ADAPT_REDUCTION(ReduceComplex4Ref, float_Complex_t, CppComplexFloat, CMPLXF, RARGS, REDUCE_ARG_NAMES) #undef RARGS #define RARGS REDUCE_ARGS(float_Complex_t, float_Complex_t_value_op) ADAPT_REDUCTION(ReduceComplex4Value, float_Complex_t, CppComplexFloat, CMPLXF, RARGS, REDUCE_ARG_NAMES) #undef RARGS #define RARGS REDUCE_ARGS(double_Complex_t, double_Complex_t_ref_op) ADAPT_REDUCTION(ReduceComplex8Ref, double_Complex_t, CppComplexDouble, CMPLX, RARGS, REDUCE_ARG_NAMES) #undef RARGS #define RARGS REDUCE_ARGS(double_Complex_t, double_Complex_t_value_op) ADAPT_REDUCTION(ReduceComplex8Value, double_Complex_t, CppComplexDouble, CMPLX, RARGS, REDUCE_ARG_NAMES) #undef RARGS #if HAS_FLOAT80 #define RARGS REDUCE_ARGS(long_double_Complex_t, long_double_Complex_t_ref_op) ADAPT_REDUCTION(ReduceComplex10Ref, long_double_Complex_t, CppComplexLongDouble, CMPLXL, RARGS, REDUCE_ARG_NAMES) #undef RARGS #define RARGS REDUCE_ARGS(long_double_Complex_t, long_double_Complex_t_value_op) ADAPT_REDUCTION(ReduceComplex10Value, long_double_Complex_t, CppComplexLongDouble, CMPLXL, RARGS, REDUCE_ARG_NAMES) #undef RARGS #endif #if HAS_LDBL128 || HAS_FLOAT128 #define RARGS REDUCE_ARGS(CFloat128ComplexType, CFloat128ComplexType_ref_op) ADAPT_REDUCTION(ReduceComplex16Ref, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, RARGS, REDUCE_ARG_NAMES) #undef RARGS #define RARGS REDUCE_ARGS(CFloat128ComplexType, CFloat128ComplexType_value_op) ADAPT_REDUCTION(ReduceComplex16Value, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, RARGS, REDUCE_ARG_NAMES) #undef RARGS #endif