mirror-llvm-project/flang/lib/evaluate/fold-complex.cpp
Alexis Perry 352d347aa5 [flang] Changed *.cc file extension to *.cpp (updated scripts) (flang-compiler/f18#958)
Updated CMake files accordingly, using better regex
Updated license headers to match new extension and fit within 80 columns
Updated other comments within files that referred to the old extension

Original-commit: flang-compiler/f18@ae7721e611
Reviewed-on: https://github.com/flang-compiler/f18/pull/958
2020-01-27 18:18:45 -08:00

80 lines
3.3 KiB
C++

//===-- lib/evaluate/fold-complex.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
//
//===----------------------------------------------------------------------===//
#include "fold-implementation.h"
namespace Fortran::evaluate {
template<int KIND>
Expr<Type<TypeCategory::Complex, KIND>> FoldIntrinsicFunction(
FoldingContext &context,
FunctionRef<Type<TypeCategory::Complex, KIND>> &&funcRef) {
using T = Type<TypeCategory::Complex, KIND>;
ActualArguments &args{funcRef.arguments()};
auto *intrinsic{std::get_if<SpecificIntrinsic>(&funcRef.proc().u)};
CHECK(intrinsic);
std::string name{intrinsic->name};
if (name == "acos" || name == "acosh" || name == "asin" || name == "asinh" ||
name == "atan" || name == "atanh" || name == "cos" || name == "cosh" ||
name == "exp" || name == "log" || name == "sin" || name == "sinh" ||
name == "sqrt" || name == "tan" || name == "tanh") {
if (auto callable{context.hostIntrinsicsLibrary()
.GetHostProcedureWrapper<Scalar, T, T>(name)}) {
return FoldElementalIntrinsic<T, T>(
context, std::move(funcRef), *callable);
} else {
context.messages().Say(
"%s(complex(kind=%d)) cannot be folded on host"_en_US, name, KIND);
}
} else if (name == "conjg") {
return FoldElementalIntrinsic<T, T>(
context, std::move(funcRef), &Scalar<T>::CONJG);
} else if (name == "cmplx") {
using Part = typename T::Part;
if (args.size() == 1) {
if (auto *x{UnwrapExpr<Expr<SomeComplex>>(args[0])}) {
return Fold(context, ConvertToType<T>(std::move(*x)));
}
Expr<SomeType> re{std::move(*args[0].value().UnwrapExpr())};
Expr<SomeType> im{AsGenericExpr(Constant<Part>{Scalar<Part>{}})};
return Fold(context,
Expr<T>{ComplexConstructor<KIND>{ToReal<KIND>(context, std::move(re)),
ToReal<KIND>(context, std::move(im))}});
}
CHECK(args.size() == 2 || args.size() == 3);
Expr<SomeType> re{std::move(*args[0].value().UnwrapExpr())};
Expr<SomeType> im{args[1] ? std::move(*args[1].value().UnwrapExpr())
: AsGenericExpr(Constant<Part>{Scalar<Part>{}})};
return Fold(context,
Expr<T>{ComplexConstructor<KIND>{ToReal<KIND>(context, std::move(re)),
ToReal<KIND>(context, std::move(im))}});
} else if (name == "merge") {
return FoldMerge<T>(context, std::move(funcRef));
}
// TODO: cshift, dot_product, eoshift, matmul, pack, product,
// reduce, spread, sum, transfer, transpose, unpack
return Expr<T>{std::move(funcRef)};
}
template<int KIND>
Expr<Type<TypeCategory::Complex, KIND>> FoldOperation(
FoldingContext &context, ComplexConstructor<KIND> &&x) {
if (auto array{ApplyElementwise(context, x)}) {
return *array;
}
using Result = Type<TypeCategory::Complex, KIND>;
if (auto folded{OperandsAreConstants(x)}) {
return Expr<Result>{
Constant<Result>{Scalar<Result>{folded->first, folded->second}}};
}
return Expr<Result>{std::move(x)};
}
FOR_EACH_COMPLEX_KIND(template class ExpressionBase, )
template class ExpressionBase<SomeComplex>;
}