| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> |
| |
| This software is provided 'as-is', without any express or implied |
| warranty. In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; you must not |
| claim that you wrote the original software. If you use this software |
| in a product, an acknowledgment in the product documentation would be |
| appreciated but is not required. |
| 2. Altered source versions must be plainly marked as such, and must not be |
| misrepresented as being the original software. |
| 3. This notice may not be removed or altered from any source distribution. |
| */ |
| #include "SDL_internal.h" |
| |
| /* This file contains portable stdlib functions for SDL */ |
| |
| #include "../libm/math_libm.h" |
| |
| double SDL_atan(double x) |
| { |
| #ifdef HAVE_ATAN |
| return atan(x); |
| #else |
| return SDL_uclibc_atan(x); |
| #endif |
| } |
| |
| float SDL_atanf(float x) |
| { |
| #ifdef HAVE_ATANF |
| return atanf(x); |
| #else |
| return (float)SDL_atan((double)x); |
| #endif |
| } |
| |
| double SDL_atan2(double y, double x) |
| { |
| #ifdef HAVE_ATAN2 |
| return atan2(y, x); |
| #else |
| return SDL_uclibc_atan2(y, x); |
| #endif |
| } |
| |
| float SDL_atan2f(float y, float x) |
| { |
| #ifdef HAVE_ATAN2F |
| return atan2f(y, x); |
| #else |
| return (float)SDL_atan2((double)y, (double)x); |
| #endif |
| } |
| |
| double SDL_acos(double val) |
| { |
| #ifdef HAVE_ACOS |
| return acos(val); |
| #else |
| double result; |
| if (val == -1.0) { |
| result = SDL_PI_D; |
| } else { |
| result = SDL_atan(SDL_sqrt(1.0 - val * val) / val); |
| if (result < 0.0) { |
| result += SDL_PI_D; |
| } |
| } |
| return result; |
| #endif |
| } |
| |
| float SDL_acosf(float val) |
| { |
| #ifdef HAVE_ACOSF |
| return acosf(val); |
| #else |
| return (float)SDL_acos((double)val); |
| #endif |
| } |
| |
| double SDL_asin(double val) |
| { |
| #ifdef HAVE_ASIN |
| return asin(val); |
| #else |
| double result; |
| if (val == -1.0) { |
| result = -(SDL_PI_D / 2.0); |
| } else { |
| result = (SDL_PI_D / 2.0) - SDL_acos(val); |
| } |
| return result; |
| #endif |
| } |
| |
| float SDL_asinf(float val) |
| { |
| #ifdef HAVE_ASINF |
| return asinf(val); |
| #else |
| return (float)SDL_asin((double)val); |
| #endif |
| } |
| |
| double SDL_ceil(double x) |
| { |
| #ifdef HAVE_CEIL |
| return ceil(x); |
| #else |
| double integer = SDL_floor(x); |
| double fraction = x - integer; |
| if (fraction > 0.0) { |
| integer += 1.0; |
| } |
| return integer; |
| #endif /* HAVE_CEIL */ |
| } |
| |
| float SDL_ceilf(float x) |
| { |
| #ifdef HAVE_CEILF |
| return ceilf(x); |
| #else |
| return (float)SDL_ceil((double)x); |
| #endif |
| } |
| |
| double SDL_copysign(double x, double y) |
| { |
| #ifdef HAVE_COPYSIGN |
| return copysign(x, y); |
| #elif defined(HAVE__COPYSIGN) |
| return _copysign(x, y); |
| #elif defined(__WATCOMC__) && defined(__386__) |
| /* this is nasty as hell, but it works.. */ |
| unsigned int *xi = (unsigned int *)&x, |
| *yi = (unsigned int *)&y; |
| xi[1] = (yi[1] & 0x80000000) | (xi[1] & 0x7fffffff); |
| return x; |
| #else |
| return SDL_uclibc_copysign(x, y); |
| #endif /* HAVE_COPYSIGN */ |
| } |
| |
| float SDL_copysignf(float x, float y) |
| { |
| #ifdef HAVE_COPYSIGNF |
| return copysignf(x, y); |
| #else |
| return (float)SDL_copysign((double)x, (double)y); |
| #endif |
| } |
| |
| double SDL_cos(double x) |
| { |
| #ifdef HAVE_COS |
| return cos(x); |
| #else |
| return SDL_uclibc_cos(x); |
| #endif |
| } |
| |
| float SDL_cosf(float x) |
| { |
| #ifdef HAVE_COSF |
| return cosf(x); |
| #else |
| return (float)SDL_cos((double)x); |
| #endif |
| } |
| |
| double SDL_exp(double x) |
| { |
| #ifdef HAVE_EXP |
| return exp(x); |
| #else |
| return SDL_uclibc_exp(x); |
| #endif |
| } |
| |
| float SDL_expf(float x) |
| { |
| #ifdef HAVE_EXPF |
| return expf(x); |
| #else |
| return (float)SDL_exp((double)x); |
| #endif |
| } |
| |
| double SDL_fabs(double x) |
| { |
| #ifdef HAVE_FABS |
| return fabs(x); |
| #else |
| return SDL_uclibc_fabs(x); |
| #endif |
| } |
| |
| float SDL_fabsf(float x) |
| { |
| #ifdef HAVE_FABSF |
| return fabsf(x); |
| #else |
| return (float)SDL_fabs((double)x); |
| #endif |
| } |
| |
| double SDL_floor(double x) |
| { |
| #ifdef HAVE_FLOOR |
| return floor(x); |
| #else |
| return SDL_uclibc_floor(x); |
| #endif |
| } |
| |
| float SDL_floorf(float x) |
| { |
| #ifdef HAVE_FLOORF |
| return floorf(x); |
| #else |
| return (float)SDL_floor((double)x); |
| #endif |
| } |
| |
| double SDL_trunc(double x) |
| { |
| #ifdef HAVE_TRUNC |
| return trunc(x); |
| #else |
| if (x >= 0.0f) { |
| return SDL_floor(x); |
| } else { |
| return SDL_ceil(x); |
| } |
| #endif |
| } |
| |
| float SDL_truncf(float x) |
| { |
| #ifdef HAVE_TRUNCF |
| return truncf(x); |
| #else |
| return (float)SDL_trunc((double)x); |
| #endif |
| } |
| |
| double SDL_fmod(double x, double y) |
| { |
| #ifdef HAVE_FMOD |
| return fmod(x, y); |
| #else |
| return SDL_uclibc_fmod(x, y); |
| #endif |
| } |
| |
| float SDL_fmodf(float x, float y) |
| { |
| #ifdef HAVE_FMODF |
| return fmodf(x, y); |
| #else |
| return (float)SDL_fmod((double)x, (double)y); |
| #endif |
| } |
| |
| double SDL_log(double x) |
| { |
| #ifdef HAVE_LOG |
| return log(x); |
| #else |
| return SDL_uclibc_log(x); |
| #endif |
| } |
| |
| float SDL_logf(float x) |
| { |
| #ifdef HAVE_LOGF |
| return logf(x); |
| #else |
| return (float)SDL_log((double)x); |
| #endif |
| } |
| |
| double SDL_log10(double x) |
| { |
| #ifdef HAVE_LOG10 |
| return log10(x); |
| #else |
| return SDL_uclibc_log10(x); |
| #endif |
| } |
| |
| float SDL_log10f(float x) |
| { |
| #ifdef HAVE_LOG10F |
| return log10f(x); |
| #else |
| return (float)SDL_log10((double)x); |
| #endif |
| } |
| |
| double SDL_modf(double x, double *y) |
| { |
| #ifdef HAVE_MODF |
| return modf(x, y); |
| #else |
| return SDL_uclibc_modf(x, y); |
| #endif |
| } |
| |
| float SDL_modff(float x, float *y) |
| { |
| #ifdef HAVE_MODFF |
| return modff(x, y); |
| #else |
| double double_result, double_y; |
| double_result = SDL_modf((double)x, &double_y); |
| *y = (float)double_y; |
| return (float)double_result; |
| #endif |
| } |
| |
| double SDL_pow(double x, double y) |
| { |
| #ifdef HAVE_POW |
| return pow(x, y); |
| #else |
| return SDL_uclibc_pow(x, y); |
| #endif |
| } |
| |
| float SDL_powf(float x, float y) |
| { |
| #ifdef HAVE_POWF |
| return powf(x, y); |
| #else |
| return (float)SDL_pow((double)x, (double)y); |
| #endif |
| } |
| |
| double SDL_round(double arg) |
| { |
| #if defined HAVE_ROUND |
| return round(arg); |
| #else |
| if (arg >= 0.0) { |
| return SDL_floor(arg + 0.5); |
| } else { |
| return SDL_ceil(arg - 0.5); |
| } |
| #endif |
| } |
| |
| float SDL_roundf(float arg) |
| { |
| #if defined HAVE_ROUNDF |
| return roundf(arg); |
| #else |
| return (float)SDL_round((double)arg); |
| #endif |
| } |
| |
| long SDL_lround(double arg) |
| { |
| #if defined HAVE_LROUND |
| return lround(arg); |
| #else |
| return (long)SDL_round(arg); |
| #endif |
| } |
| |
| long SDL_lroundf(float arg) |
| { |
| #if defined HAVE_LROUNDF |
| return lroundf(arg); |
| #else |
| return (long)SDL_round((double)arg); |
| #endif |
| } |
| |
| double SDL_scalbn(double x, int n) |
| { |
| #ifdef HAVE_SCALBN |
| return scalbn(x, n); |
| #elif defined(HAVE__SCALB) |
| return _scalb(x, n); |
| #elif defined(HAVE_LIBC) && defined(HAVE_FLOAT_H) && (FLT_RADIX == 2) |
| /* from scalbn(3): If FLT_RADIX equals 2 (which is |
| * usual), then scalbn() is equivalent to ldexp(3). */ |
| return ldexp(x, n); |
| #else |
| return SDL_uclibc_scalbn(x, n); |
| #endif |
| } |
| |
| float SDL_scalbnf(float x, int n) |
| { |
| #ifdef HAVE_SCALBNF |
| return scalbnf(x, n); |
| #else |
| return (float)SDL_scalbn((double)x, n); |
| #endif |
| } |
| |
| double SDL_sin(double x) |
| { |
| #ifdef HAVE_SIN |
| return sin(x); |
| #else |
| return SDL_uclibc_sin(x); |
| #endif |
| } |
| |
| float SDL_sinf(float x) |
| { |
| #ifdef HAVE_SINF |
| return sinf(x); |
| #else |
| return (float)SDL_sin((double)x); |
| #endif |
| } |
| |
| double SDL_sqrt(double x) |
| { |
| #ifdef HAVE_SQRT |
| return sqrt(x); |
| #else |
| return SDL_uclibc_sqrt(x); |
| #endif |
| } |
| |
| float SDL_sqrtf(float x) |
| { |
| #ifdef HAVE_SQRTF |
| return sqrtf(x); |
| #else |
| return (float)SDL_sqrt((double)x); |
| #endif |
| } |
| |
| double SDL_tan(double x) |
| { |
| #ifdef HAVE_TAN |
| return tan(x); |
| #else |
| return SDL_uclibc_tan(x); |
| #endif |
| } |
| |
| float SDL_tanf(float x) |
| { |
| #ifdef HAVE_TANF |
| return tanf(x); |
| #else |
| return (float)SDL_tan((double)x); |
| #endif |
| } |
| |
| int SDL_abs(int x) |
| { |
| #ifdef HAVE_ABS |
| return abs(x); |
| #else |
| return (x < 0) ? -x : x; |
| #endif |
| } |
| |
| int SDL_isalpha(int x) { return (SDL_isupper(x)) || (SDL_islower(x)); } |
| int SDL_isalnum(int x) { return (SDL_isalpha(x)) || (SDL_isdigit(x)); } |
| int SDL_isdigit(int x) { return ((x) >= '0') && ((x) <= '9'); } |
| int SDL_isxdigit(int x) { return (((x) >= 'A') && ((x) <= 'F')) || (((x) >= 'a') && ((x) <= 'f')) || (SDL_isdigit(x)); } |
| int SDL_ispunct(int x) { return (SDL_isgraph(x)) && (!SDL_isalnum(x)); } |
| int SDL_isspace(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n') || ((x) == '\f') || ((x) == '\v'); } |
| int SDL_isupper(int x) { return ((x) >= 'A') && ((x) <= 'Z'); } |
| int SDL_islower(int x) { return ((x) >= 'a') && ((x) <= 'z'); } |
| int SDL_isprint(int x) { return ((x) >= ' ') && ((x) < '\x7f'); } |
| int SDL_isgraph(int x) { return (SDL_isprint(x)) && ((x) != ' '); } |
| int SDL_iscntrl(int x) { return (((x) >= '\0') && ((x) <= '\x1f')) || ((x) == '\x7f'); } |
| int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A' + ((x) - 'a')) : (x); } |
| int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a' + ((x) - 'A')) : (x); } |
| int SDL_isblank(int x) { return ((x) == ' ') || ((x) == '\t'); } |
| |
| void *SDL_aligned_alloc(size_t alignment, size_t size) |
| { |
| size_t padding; |
| Uint8 *retval = NULL; |
| |
| if (alignment < sizeof(void*)) { |
| alignment = sizeof(void*); |
| } |
| padding = (alignment - (size % alignment)); |
| |
| if (SDL_size_add_overflow(size, alignment, &size) == 0 && |
| SDL_size_add_overflow(size, sizeof(void *), &size) == 0 && |
| SDL_size_add_overflow(size, padding, &size) == 0) { |
| void *original = SDL_malloc(size); |
| if (original) { |
| /* Make sure we have enough space to store the original pointer */ |
| retval = (Uint8 *)original + sizeof(original); |
| |
| /* Align the pointer we're going to return */ |
| retval += alignment - (((size_t)retval) % alignment); |
| |
| /* Store the original pointer right before the returned value */ |
| SDL_memcpy(retval - sizeof(original), &original, sizeof(original)); |
| } |
| } |
| return retval; |
| } |
| |
| void SDL_aligned_free(void *mem) |
| { |
| if (mem) { |
| void *original; |
| SDL_memcpy(&original, ((Uint8 *)mem - sizeof(original)), sizeof(original)); |
| SDL_free(original); |
| } |
| } |