1 /*===-- flang/runtime/complex-powi.cpp ----------------------------*- C++ -*-===
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 "flang/Runtime/entry-names.h"
14 #ifdef __clang_major__
15 #pragma clang diagnostic ignored "-Wc99-extensions"
18 template <typename C
, typename I
> C
tgpowi(C base
, I exp
) {
23 bool invertResult
{exp
< 0};
24 bool isMin
{exp
== std::numeric_limits
<I
>::min()};
27 exp
= std::numeric_limits
<I
>::max();
36 while ((exp
& 1) == 0) {
63 // With most compilers, C complex is implemented as a builtin type that may have
64 // specific ABI requirements
65 extern "C" float _Complex
RTNAME(cpowi
)(float _Complex base
, std::int32_t exp
) {
66 return tgpowi(base
, exp
);
69 extern "C" double _Complex
RTNAME(zpowi
)(
70 double _Complex base
, std::int32_t exp
) {
71 return tgpowi(base
, exp
);
74 extern "C" float _Complex
RTNAME(cpowk
)(float _Complex base
, std::int64_t exp
) {
75 return tgpowi(base
, exp
);
78 extern "C" double _Complex
RTNAME(zpowk
)(
79 double _Complex base
, std::int64_t exp
) {
80 return tgpowi(base
, exp
);
83 // on MSVC, C complex is always just a struct of two members as it is not
84 // supported as a builtin type. So we use C++ complex here as that has the
85 // same ABI and layout. See:
86 // https://learn.microsoft.com/en-us/cpp/c-runtime-library/complex-math-support
89 // MSVC doesn't allow including <ccomplex> or <complex.h> in C++17 mode to get
90 // the Windows definitions of these structs so just redefine here.
101 extern "C" Fcomplex
RTNAME(cpowi
)(Fcomplex base
, std::int32_t exp
) {
102 auto cppbase
= *(std::complex<float> *)(&base
);
103 auto cppres
= tgpowi(cppbase
, exp
);
104 return *(Fcomplex
*)(&cppres
);
107 extern "C" Dcomplex
RTNAME(zpowi
)(Dcomplex base
, std::int32_t exp
) {
108 auto cppbase
= *(std::complex<double> *)(&base
);
109 auto cppres
= tgpowi(cppbase
, exp
);
110 return *(Dcomplex
*)(&cppres
);
113 extern "C" Fcomplex
RTNAME(cpowk
)(Fcomplex base
, std::int64_t exp
) {
114 auto cppbase
= *(std::complex<float> *)(&base
);
115 auto cppres
= tgpowi(cppbase
, exp
);
116 return *(Fcomplex
*)(&cppres
);
119 extern "C" Dcomplex
RTNAME(zpowk
)(Dcomplex base
, std::int32_t exp
) {
120 auto cppbase
= *(std::complex<double> *)(&base
);
121 auto cppres
= tgpowi(cppbase
, exp
);
122 return *(Dcomplex
*)(&cppres
);