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/Common/float128.h"
10 #include "flang/Runtime/entry-names.h"
15 #ifdef __clang_major__
16 #pragma clang diagnostic ignored "-Wc99-extensions"
19 template <typename C
, typename I
> C
tgpowi(C base
, I exp
) {
24 bool invertResult
{exp
< 0};
25 bool isMin
{exp
== std::numeric_limits
<I
>::min()};
28 exp
= std::numeric_limits
<I
>::max();
37 while ((exp
& 1) == 0) {
64 // With most compilers, C complex is implemented as a builtin type that may have
65 // specific ABI requirements
66 extern "C" float _Complex
RTNAME(cpowi
)(float _Complex base
, std::int32_t exp
) {
67 return tgpowi(base
, exp
);
70 extern "C" double _Complex
RTNAME(zpowi
)(
71 double _Complex base
, std::int32_t exp
) {
72 return tgpowi(base
, exp
);
75 extern "C" float _Complex
RTNAME(cpowk
)(float _Complex base
, std::int64_t exp
) {
76 return tgpowi(base
, exp
);
79 extern "C" double _Complex
RTNAME(zpowk
)(
80 double _Complex base
, std::int64_t exp
) {
81 return tgpowi(base
, exp
);
84 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
85 // Duplicate CFloat128ComplexType definition from flang/Common/float128.h.
86 // float128.h does not define it for C++, because _Complex triggers
87 // c99-extension warnings. We decided to disable warnings for this
88 // particular file, so we can use _Complex here.
89 #if LDBL_MANT_DIG == 113
90 typedef long double _Complex Qcomplex
;
92 #if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
93 typedef _Complex
float __attribute__((mode(TC
))) Qcomplex
;
95 typedef _Complex
float __attribute__((mode(KC
))) Qcomplex
;
99 extern "C" Qcomplex
RTNAME(cqpowi
)(Qcomplex base
, std::int32_t exp
) {
100 return tgpowi(base
, exp
);
102 extern "C" Qcomplex
RTNAME(cqpowk
)(Qcomplex base
, std::int64_t exp
) {
103 return tgpowi(base
, exp
);
108 // on MSVC, C complex is always just a struct of two members as it is not
109 // supported as a builtin type. So we use C++ complex here as that has the
110 // same ABI and layout. See:
111 // https://learn.microsoft.com/en-us/cpp/c-runtime-library/complex-math-support
114 // MSVC doesn't allow including <ccomplex> or <complex.h> in C++17 mode to get
115 // the Windows definitions of these structs so just redefine here.
126 extern "C" Fcomplex
RTNAME(cpowi
)(Fcomplex base
, std::int32_t exp
) {
127 auto cppbase
= *(std::complex<float> *)(&base
);
128 auto cppres
= tgpowi(cppbase
, exp
);
129 return *(Fcomplex
*)(&cppres
);
132 extern "C" Dcomplex
RTNAME(zpowi
)(Dcomplex base
, std::int32_t exp
) {
133 auto cppbase
= *(std::complex<double> *)(&base
);
134 auto cppres
= tgpowi(cppbase
, exp
);
135 return *(Dcomplex
*)(&cppres
);
138 extern "C" Fcomplex
RTNAME(cpowk
)(Fcomplex base
, std::int64_t exp
) {
139 auto cppbase
= *(std::complex<float> *)(&base
);
140 auto cppres
= tgpowi(cppbase
, exp
);
141 return *(Fcomplex
*)(&cppres
);
144 extern "C" Dcomplex
RTNAME(zpowk
)(Dcomplex base
, std::int64_t exp
) {
145 auto cppbase
= *(std::complex<double> *)(&base
);
146 auto cppres
= tgpowi(cppbase
, exp
);
147 return *(Dcomplex
*)(&cppres
);
150 #if LDBL_MANT_DIG == 113 || HAS_FLOAT128
156 extern "C" Dcomplex
RTNAME(cqpowi
)(Qcomplex base
, std::int32_t exp
) {
157 auto cppbase
= *(std::complex<CFloat128Type
> *)(&base
);
158 auto cppres
= tgpowi(cppbase
, exp
);
159 return *(Qcomplex
*)(&cppres
);
162 extern "C" Dcomplex
RTNAME(cqpowk
)(Qcomplex base
, std::int64_t exp
) {
163 auto cppbase
= *(std::complex<CFloat128Type
> *)(&base
);
164 auto cppres
= tgpowi(cppbase
, exp
);
165 return *(Qcomplex
*)(&cppres
);