Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce math_compat.h for older Android versions (#28567)
Summary: When building with Android NDK platforms prior to android-21, and when building for Android with libstdc++, there are some gaps in the C and C++ standard libraries. We use both for our internal 32-bit builds, so we need PyTorch to support this platform. All of the gaps are filled with this math_compat.h header, which needs to be included in any file that uses one of the functions that are not properly defined on Android. The file is a bit hack-tastic, but it is only used on a platform that is not receiving updates, so there shouldn't be a risk of breakage in the future. Pull Request resolved: #28567 Test Plan: Internal android build. Differential Revision: D18099513 Pulled By: dreiss fbshipit-source-id: 020aab19c6fa083206310b018925d92275d4a548
- Loading branch information
1 parent
cb72c9f
commit 0d9dc46
Showing
10 changed files
with
124 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#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__) | ||
|
||
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"); | ||
} | ||
|
||
// 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); | ||
} | ||
inline double log2(double arg) { | ||
return ::log(arg) / ::log(2.0); | ||
} | ||
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); | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters