llvm-project

Форк
0
/
complex-powi.cpp 
168 строк · 4.3 Кб
1
/*===-- flang/runtime/complex-powi.cpp ----------------------------*- C++ -*-===
2
 *
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
6
 *
7
 * ===-----------------------------------------------------------------------===
8
 */
9
#include "flang/Common/float128.h"
10
#include "flang/Runtime/entry-names.h"
11
#include <cstdint>
12
#include <cstdio>
13
#include <limits>
14

15
#ifdef __clang_major__
16
#pragma clang diagnostic ignored "-Wc99-extensions"
17
#endif
18

19
template <typename C, typename I> C tgpowi(C base, I exp) {
20
  if (exp == 0) {
21
    return C{1};
22
  }
23

24
  bool invertResult{exp < 0};
25
  bool isMin{exp == std::numeric_limits<I>::min()};
26

27
  if (isMin) {
28
    exp = std::numeric_limits<I>::max();
29
  }
30

31
  if (exp < 0) {
32
    exp = exp * -1;
33
  }
34

35
  C origBase{base};
36

37
  while ((exp & 1) == 0) {
38
    base *= base;
39
    exp >>= 1;
40
  }
41

42
  C acc{base};
43

44
  while (exp > 1) {
45
    exp >>= 1;
46
    base *= base;
47
    if ((exp & 1) == 1) {
48
      acc *= base;
49
    }
50
  }
51

52
  if (isMin) {
53
    acc *= origBase;
54
  }
55

56
  if (invertResult) {
57
    acc = C{1} / acc;
58
  }
59

60
  return acc;
61
}
62

63
#ifndef _MSC_VER
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);
68
}
69

70
extern "C" double _Complex RTNAME(zpowi)(
71
    double _Complex base, std::int32_t exp) {
72
  return tgpowi(base, exp);
73
}
74

75
extern "C" float _Complex RTNAME(cpowk)(float _Complex base, std::int64_t exp) {
76
  return tgpowi(base, exp);
77
}
78

79
extern "C" double _Complex RTNAME(zpowk)(
80
    double _Complex base, std::int64_t exp) {
81
  return tgpowi(base, exp);
82
}
83

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;
91
#elif HAS_FLOAT128
92
#if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__)
93
typedef _Complex float __attribute__((mode(TC))) Qcomplex;
94
#else
95
typedef _Complex float __attribute__((mode(KC))) Qcomplex;
96
#endif
97
#endif
98

99
extern "C" Qcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) {
100
  return tgpowi(base, exp);
101
}
102
extern "C" Qcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) {
103
  return tgpowi(base, exp);
104
}
105
#endif
106

107
#else
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
112
#include <complex>
113

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.
116
struct Fcomplex {
117
  float re;
118
  float im;
119
};
120

121
struct Dcomplex {
122
  double re;
123
  double im;
124
};
125

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);
130
}
131

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);
136
}
137

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);
142
}
143

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);
148
}
149

150
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
151
struct Qcomplex {
152
  CFloat128Type re;
153
  CFloat128Type im;
154
};
155

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);
160
}
161

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);
166
}
167
#endif
168
#endif
169

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.