1 //===-- lib/Evaluate/fold-complex.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 #include "fold-implementation.h"
11 namespace Fortran::evaluate
{
14 Expr
<Type
<TypeCategory::Complex
, KIND
>> FoldIntrinsicFunction(
15 FoldingContext
&context
,
16 FunctionRef
<Type
<TypeCategory::Complex
, KIND
>> &&funcRef
) {
17 using T
= Type
<TypeCategory::Complex
, KIND
>;
18 ActualArguments
&args
{funcRef
.arguments()};
19 auto *intrinsic
{std::get_if
<SpecificIntrinsic
>(&funcRef
.proc().u
)};
21 std::string name
{intrinsic
->name
};
22 if (name
== "acos" || name
== "acosh" || name
== "asin" || name
== "asinh" ||
23 name
== "atan" || name
== "atanh" || name
== "cos" || name
== "cosh" ||
24 name
== "exp" || name
== "log" || name
== "sin" || name
== "sinh" ||
25 name
== "sqrt" || name
== "tan" || name
== "tanh") {
26 if (auto callable
{GetHostRuntimeWrapper
<T
, T
>(name
)}) {
27 return FoldElementalIntrinsic
<T
, T
>(
28 context
, std::move(funcRef
), *callable
);
30 context
.messages().Say(
31 "%s(complex(kind=%d)) cannot be folded on host"_en_US
, name
, KIND
);
33 } else if (name
== "conjg") {
34 return FoldElementalIntrinsic
<T
, T
>(
35 context
, std::move(funcRef
), &Scalar
<T
>::CONJG
);
36 } else if (name
== "cmplx") {
37 using Part
= typename
T::Part
;
38 if (args
.size() == 2) { // CMPLX(X, [KIND])
39 if (auto *x
{UnwrapExpr
<Expr
<SomeComplex
>>(args
[0])}) {
40 return Fold(context
, ConvertToType
<T
>(std::move(*x
)));
42 Expr
<SomeType
> re
{std::move(*args
[0].value().UnwrapExpr())};
43 Expr
<SomeType
> im
{AsGenericExpr(Constant
<Part
>{Scalar
<Part
>{}})};
45 Expr
<T
>{ComplexConstructor
<KIND
>{ToReal
<KIND
>(context
, std::move(re
)),
46 ToReal
<KIND
>(context
, std::move(im
))}});
48 // CMPLX(X, [Y, KIND])
49 CHECK(args
.size() == 3);
50 Expr
<SomeType
> re
{std::move(*args
[0].value().UnwrapExpr())};
51 Expr
<SomeType
> im
{args
[1] ? std::move(*args
[1].value().UnwrapExpr())
52 : AsGenericExpr(Constant
<Part
>{Scalar
<Part
>{}})};
54 Expr
<T
>{ComplexConstructor
<KIND
>{ToReal
<KIND
>(context
, std::move(re
)),
55 ToReal
<KIND
>(context
, std::move(im
))}});
56 } else if (name
== "merge") {
57 return FoldMerge
<T
>(context
, std::move(funcRef
));
59 // TODO: cshift, dot_product, eoshift, matmul, pack, product,
60 // reduce, spread, sum, transfer, transpose, unpack
61 return Expr
<T
>{std::move(funcRef
)};
65 Expr
<Type
<TypeCategory::Complex
, KIND
>> FoldOperation(
66 FoldingContext
&context
, ComplexConstructor
<KIND
> &&x
) {
67 if (auto array
{ApplyElementwise(context
, x
)}) {
70 using Result
= Type
<TypeCategory::Complex
, KIND
>;
71 if (auto folded
{OperandsAreConstants(x
)}) {
73 Constant
<Result
>{Scalar
<Result
>{folded
->first
, folded
->second
}}};
75 return Expr
<Result
>{std::move(x
)};
78 FOR_EACH_COMPLEX_KIND(template class ExpressionBase
, )
79 template class ExpressionBase
<SomeComplex
>;
80 } // namespace Fortran::evaluate