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/cpp-type.h"
11 #include "flang/Runtime/entry-names.h"
16 namespace Fortran::runtime
{
17 #ifdef __clang_major__
18 #pragma clang diagnostic ignored "-Wc99-extensions"
21 template <typename C
, typename I
> C
tgpowi(C base
, I exp
) {
26 bool invertResult
{exp
< 0};
27 bool isMin
{exp
== std::numeric_limits
<I
>::min()};
30 exp
= std::numeric_limits
<I
>::max();
39 while ((exp
& 1) == 0) {
66 // With most compilers, C complex is implemented as a builtin type that may have
67 // specific ABI requirements
68 extern "C" float _Complex
RTNAME(cpowi
)(float _Complex base
, std::int32_t exp
) {
69 return tgpowi(base
, exp
);
72 extern "C" double _Complex
RTNAME(zpowi
)(
73 double _Complex base
, std::int32_t exp
) {
74 return tgpowi(base
, exp
);
77 extern "C" float _Complex
RTNAME(cpowk
)(float _Complex base
, std::int64_t exp
) {
78 return tgpowi(base
, exp
);
81 extern "C" double _Complex
RTNAME(zpowk
)(
82 double _Complex base
, std::int64_t exp
) {
83 return tgpowi(base
, exp
);
86 #if HAS_LDBL128 || HAS_FLOAT128
87 // Duplicate CFloat128ComplexType definition from flang/Common/float128.h.
88 // float128.h does not define it for C++, because _Complex triggers
89 // c99-extension warnings. We decided to disable warnings for this
90 // particular file, so we can use _Complex here.
92 typedef long double _Complex Qcomplex
;
94 #if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
95 typedef _Complex
float __attribute__((mode(TC
))) Qcomplex
;
97 typedef _Complex
float __attribute__((mode(KC
))) Qcomplex
;
101 extern "C" Qcomplex
RTNAME(cqpowi
)(Qcomplex base
, std::int32_t exp
) {
102 return tgpowi(base
, exp
);
104 extern "C" Qcomplex
RTNAME(cqpowk
)(Qcomplex base
, std::int64_t exp
) {
105 return tgpowi(base
, exp
);
110 // on MSVC, C complex is always just a struct of two members as it is not
111 // supported as a builtin type. So we use C++ complex here as that has the
112 // same ABI and layout. See:
113 // https://learn.microsoft.com/en-us/cpp/c-runtime-library/complex-math-support
116 // MSVC doesn't allow including <ccomplex> or <complex.h> in C++17 mode to get
117 // the Windows definitions of these structs so just redefine here.
119 CppTypeFor
<TypeCategory::Real
, 4> re
;
120 CppTypeFor
<TypeCategory::Real
, 4> im
;
124 CppTypeFor
<TypeCategory::Real
, 8> re
;
125 CppTypeFor
<TypeCategory::Real
, 8> im
;
128 extern "C" Fcomplex
RTNAME(cpowi
)(Fcomplex base
, std::int32_t exp
) {
129 auto cppbase
= *(CppTypeFor
<TypeCategory::Complex
, 4> *)(&base
);
130 auto cppres
= tgpowi(cppbase
, exp
);
131 return *(Fcomplex
*)(&cppres
);
134 extern "C" Dcomplex
RTNAME(zpowi
)(Dcomplex base
, std::int32_t exp
) {
135 auto cppbase
= *(CppTypeFor
<TypeCategory::Complex
, 8> *)(&base
);
136 auto cppres
= tgpowi(cppbase
, exp
);
137 return *(Dcomplex
*)(&cppres
);
140 extern "C" Fcomplex
RTNAME(cpowk
)(Fcomplex base
, std::int64_t exp
) {
141 auto cppbase
= *(CppTypeFor
<TypeCategory::Complex
, 4> *)(&base
);
142 auto cppres
= tgpowi(cppbase
, exp
);
143 return *(Fcomplex
*)(&cppres
);
146 extern "C" Dcomplex
RTNAME(zpowk
)(Dcomplex base
, std::int64_t exp
) {
147 auto cppbase
= *(CppTypeFor
<TypeCategory::Complex
, 8> *)(&base
);
148 auto cppres
= tgpowi(cppbase
, exp
);
149 return *(Dcomplex
*)(&cppres
);
152 #if HAS_LDBL128 || HAS_FLOAT128
158 extern "C" Dcomplex
RTNAME(cqpowi
)(Qcomplex base
, std::int32_t exp
) {
159 auto cppbase
= *(rtcmplx::complex<CFloat128Type
> *)(&base
);
160 auto cppres
= tgpowi(cppbase
, exp
);
161 return *(Qcomplex
*)(&cppres
);
164 extern "C" Dcomplex
RTNAME(cqpowk
)(Qcomplex base
, std::int64_t exp
) {
165 auto cppbase
= *(rtcmplx::complex<CFloat128Type
> *)(&base
);
166 auto cppres
= tgpowi(cppbase
, exp
);
167 return *(Qcomplex
*)(&cppres
);
171 } // namespace Fortran::runtime