File: math_compat.h

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (256 lines) | stat: -rw-r--r-- 7,552 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#pragma once

#include <cmath>

// Android NDK platform < 21 with libstdc++ has spotty C++11 support.
// Various hacks in this header allow the rest of the codebase to use
// standard APIs.
#if (defined(__ANDROID__) && __ANDROID_API__ < 21 && defined(__GLIBCXX__)) || \
    defined(__NEWLIB__)
#include <stdexcept>

namespace std {
// Import double versions of these functions from the global namespace.
using ::acosh;
using ::asinh;
using ::atanh;
using ::erf;
using ::erfc;
using ::expm1;
using ::lgamma;
using ::log1p;
using ::nearbyint;
using ::round;
using ::tgamma;
using ::trunc;
using ::truncf;

// Define float versions the same way as more recent libstdc++
inline float acosh(float x) {
  return __builtin_acoshf(x);
}
inline float asinh(float x) {
  return __builtin_asinhf(x);
}
inline float atanh(float x) {
  return __builtin_atanhf(x);
}
inline float copysign(float x, float y) {
  return __builtin_copysignf(x, y);
}
inline float erf(float x) {
  return __builtin_erff(x);
}
inline float erfc(float x) {
  return __builtin_erfcf(x);
}
inline float expm1(float x) {
  return __builtin_expm1f(x);
}
inline float fmax(float x, float y) {
  return __builtin_fmaxf(x, y);
}
inline float fmin(float x, float y) {
  return __builtin_fminf(x, y);
}
inline float lgamma(float x) {
  return __builtin_lgammaf(x);
}
inline float log1p(float x) {
  return __builtin_log1pf(x);
}
inline float nearbyint(float x) {
  return __builtin_nearbyintf(x);
}
inline float remainder(float x, float y) {
  return __builtin_remainderf(x, y);
}
inline float round(float x) {
  return __builtin_roundf(x);
}
inline float tgamma(float x) {
  return __builtin_tgammaf(x);
}
inline float trunc(float x) {
  return __builtin_truncf(x);
}

// __builtin_nexttoward isn't doesn't work.  It appears to try to
// link against the global nexttoward function, which is not present
// prior to API 18.  Just bail for now.
inline float nexttoward(float x, long double y) {
  throw std::runtime_error("std::nexttoward is not present on older Android");
}
inline double nexttoward(double x, long double y) {
  throw std::runtime_error("std::nexttoward is not present on older Android");
}

#if !defined(__NEWLIB__)
// TODO: this function needs to be implemented and tested. Currently just throw
// an error.
inline float hypot(float x, float y) {
  throw std::runtime_error("std::hypot is not implemented on older Android");
}
inline double hypot(double x, double y) {
  throw std::runtime_error("std::hypot is not implemented on older Android");
}
#else
inline float hypot(float x, float y) {
  return hypot((double)x, (double)y);
}
#endif

// TODO: this function needs to be implemented and tested. Currently just throw
// an error.
inline float igamma(float x, float y) {
  throw std::runtime_error("igamma is not implemented on older Android");
}
inline double igamma(double x, double y) {
  throw std::runtime_error("igamma is not implemented on older Android");
}
inline float igammac(float x, float y) {
  throw std::runtime_error("igammac is not implemented on older Android");
}
inline double igammac(double x, double y) {
  throw std::runtime_error("igammac is not implemented on older Android");
}

// Note: std::signbit returns true for negative zero (-0), but this
// implementation returns false.
inline bool signbit(float x) {
  return x < 0;
}
inline bool signbit(double x) {
  return x < 0;
}
inline bool signbit(long double x) {
  return x < 0;
}

#if !defined(__NEWLIB__)
// TODO: this function needs to be implemented and tested. Currently just throw
// an error.
inline float nextafter(float x, float y) {
  throw std::runtime_error(
      "std::nextafter is not implemented on older Android");
}
inline double nextafter(double x, double y) {
  throw std::runtime_error(
      "std::nextafter is not implemented on older Android");
}
#else
inline float nextafter(float x, float y) {
  return nextafter((double)x, (double)y);
}
#endif

#if !defined(__NEWLIB__)
// TODO: this function needs to be implemented and tested. Currently just throw
// an error.
inline float exp2(float x) {
  throw std::runtime_error("std::exp2 is not implemented on older Android");
}
inline double exp2(double x) {
  throw std::runtime_error("std::exp2 is not implemented on older Android");
}
#else
inline float exp2(float x) {
  return exp2((double)x);
}
#endif

// Define integral versions the same way as more recent libstdc++
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type acosh(T x) {
  return __builtin_acosh(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type asinh(T x) {
  return __builtin_asinh(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type atanh(T x) {
  return __builtin_atanh(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type erf(T x) {
  return __builtin_erf(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type erfc(T x) {
  return __builtin_erfc(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type expm1(T x) {
  return __builtin_expm1(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type lgamma(T x) {
  return __builtin_lgamma(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type log1p(T x) {
  return __builtin_log1p(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type nearbyint(
    T x) {
  return __builtin_nearbyint(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type round(T x) {
  return __builtin_round(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type tgamma(T x) {
  return __builtin_tgamma(x);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type trunc(T x) {
  return __builtin_trunc(x);
}

// Convoluted definition of these binary functions for overloads other than
// (float,float) and (double,double).  Using a template from __gnu_cxx
// is dirty, but this code is only enabled on a dead platform, so there
// shouldn't be any risk of it breaking due to updates.
template <typename T, typename U>
typename __gnu_cxx::__promote_2<T, U>::__type fmax(T x, U y) {
  typedef typename __gnu_cxx::__promote_2<T, U>::__type type;
  return fmax(type(x), type(y));
}
template <typename T, typename U>
typename __gnu_cxx::__promote_2<T, U>::__type fmin(T x, U y) {
  typedef typename __gnu_cxx::__promote_2<T, U>::__type type;
  return fmin(type(x), type(y));
}
template <typename T, typename U>
typename __gnu_cxx::__promote_2<T, U>::__type copysign(T x, U y) {
  typedef typename __gnu_cxx::__promote_2<T, U>::__type type;
  return copysign(type(x), type(y));
}
template <typename T, typename U>
typename __gnu_cxx::__promote_2<T, U>::__type remainder(T x, U y) {
  typedef typename __gnu_cxx::__promote_2<T, U>::__type type;
  return remainder(type(x), type(y));
}

// log2 is a macro on Android API < 21, so we need to define it ourselves.
inline float log2(float arg) {
  return ::log(arg) / ::log(2.0);
}
#if !defined(__NEWLIB__)
inline double log2(double arg) {
  return ::log(arg) / ::log(2.0);
}
#endif
inline long double log2(long double arg) {
  return ::log(arg) / ::log(2.0);
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value, double>::type log2(T x) {
  return ::log(x) / ::log(2.0);
}
} // namespace std

#endif