| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 | #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");}#elseinline 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");}#elseinline 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");}#elseinline 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);}#endifinline 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
 |