SDL_stdlib.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2023 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. /* This file contains portable stdlib functions for SDL */
  20. #include "../libm/math_libm.h"
  21. double
  22. SDL_atan(double x)
  23. {
  24. #ifdef HAVE_ATAN
  25. return atan(x);
  26. #else
  27. return SDL_uclibc_atan(x);
  28. #endif
  29. }
  30. float SDL_atanf(float x)
  31. {
  32. #ifdef HAVE_ATANF
  33. return atanf(x);
  34. #else
  35. return (float)SDL_atan((double)x);
  36. #endif
  37. }
  38. double
  39. SDL_atan2(double y, double x)
  40. {
  41. #ifdef HAVE_ATAN2
  42. return atan2(y, x);
  43. #else
  44. return SDL_uclibc_atan2(y, x);
  45. #endif
  46. }
  47. float SDL_atan2f(float y, float x)
  48. {
  49. #ifdef HAVE_ATAN2F
  50. return atan2f(y, x);
  51. #else
  52. return (float)SDL_atan2((double)y, (double)x);
  53. #endif
  54. }
  55. double
  56. SDL_acos(double val)
  57. {
  58. #ifdef HAVE_ACOS
  59. return acos(val);
  60. #else
  61. double result;
  62. if (val == -1.0) {
  63. result = SDL_PI_D;
  64. } else {
  65. result = SDL_atan(SDL_sqrt(1.0 - val * val) / val);
  66. if (result < 0.0) {
  67. result += SDL_PI_D;
  68. }
  69. }
  70. return result;
  71. #endif
  72. }
  73. float SDL_acosf(float val)
  74. {
  75. #ifdef HAVE_ACOSF
  76. return acosf(val);
  77. #else
  78. return (float)SDL_acos((double)val);
  79. #endif
  80. }
  81. double
  82. SDL_asin(double val)
  83. {
  84. #ifdef HAVE_ASIN
  85. return asin(val);
  86. #else
  87. double result;
  88. if (val == -1.0) {
  89. result = -(SDL_PI_D / 2.0);
  90. } else {
  91. result = (SDL_PI_D / 2.0) - SDL_acos(val);
  92. }
  93. return result;
  94. #endif
  95. }
  96. float SDL_asinf(float val)
  97. {
  98. #ifdef HAVE_ASINF
  99. return asinf(val);
  100. #else
  101. return (float)SDL_asin((double)val);
  102. #endif
  103. }
  104. double
  105. SDL_ceil(double x)
  106. {
  107. #ifdef HAVE_CEIL
  108. return ceil(x);
  109. #else
  110. double integer = SDL_floor(x);
  111. double fraction = x - integer;
  112. if (fraction > 0.0) {
  113. integer += 1.0;
  114. }
  115. return integer;
  116. #endif /* HAVE_CEIL */
  117. }
  118. float SDL_ceilf(float x)
  119. {
  120. #ifdef HAVE_CEILF
  121. return ceilf(x);
  122. #else
  123. return (float)SDL_ceil((double)x);
  124. #endif
  125. }
  126. double
  127. SDL_copysign(double x, double y)
  128. {
  129. #ifdef HAVE_COPYSIGN
  130. return copysign(x, y);
  131. #elif defined(HAVE__COPYSIGN)
  132. return _copysign(x, y);
  133. #elif defined(__WATCOMC__) && defined(__386__)
  134. /* this is nasty as hell, but it works.. */
  135. unsigned int *xi = (unsigned int *)&x,
  136. *yi = (unsigned int *)&y;
  137. xi[1] = (yi[1] & 0x80000000) | (xi[1] & 0x7fffffff);
  138. return x;
  139. #else
  140. return SDL_uclibc_copysign(x, y);
  141. #endif /* HAVE_COPYSIGN */
  142. }
  143. float SDL_copysignf(float x, float y)
  144. {
  145. #ifdef HAVE_COPYSIGNF
  146. return copysignf(x, y);
  147. #else
  148. return (float)SDL_copysign((double)x, (double)y);
  149. #endif
  150. }
  151. double
  152. SDL_cos(double x)
  153. {
  154. #ifdef HAVE_COS
  155. return cos(x);
  156. #else
  157. return SDL_uclibc_cos(x);
  158. #endif
  159. }
  160. float SDL_cosf(float x)
  161. {
  162. #ifdef HAVE_COSF
  163. return cosf(x);
  164. #else
  165. return (float)SDL_cos((double)x);
  166. #endif
  167. }
  168. double
  169. SDL_exp(double x)
  170. {
  171. #ifdef HAVE_EXP
  172. return exp(x);
  173. #else
  174. return SDL_uclibc_exp(x);
  175. #endif
  176. }
  177. float SDL_expf(float x)
  178. {
  179. #ifdef HAVE_EXPF
  180. return expf(x);
  181. #else
  182. return (float)SDL_exp((double)x);
  183. #endif
  184. }
  185. double
  186. SDL_fabs(double x)
  187. {
  188. #ifdef HAVE_FABS
  189. return fabs(x);
  190. #else
  191. return SDL_uclibc_fabs(x);
  192. #endif
  193. }
  194. float SDL_fabsf(float x)
  195. {
  196. #ifdef HAVE_FABSF
  197. return fabsf(x);
  198. #else
  199. return (float)SDL_fabs((double)x);
  200. #endif
  201. }
  202. double
  203. SDL_floor(double x)
  204. {
  205. #ifdef HAVE_FLOOR
  206. return floor(x);
  207. #else
  208. return SDL_uclibc_floor(x);
  209. #endif
  210. }
  211. float SDL_floorf(float x)
  212. {
  213. #ifdef HAVE_FLOORF
  214. return floorf(x);
  215. #else
  216. return (float)SDL_floor((double)x);
  217. #endif
  218. }
  219. double
  220. SDL_trunc(double x)
  221. {
  222. #ifdef HAVE_TRUNC
  223. return trunc(x);
  224. #else
  225. if (x >= 0.0f) {
  226. return SDL_floor(x);
  227. } else {
  228. return SDL_ceil(x);
  229. }
  230. #endif
  231. }
  232. float SDL_truncf(float x)
  233. {
  234. #ifdef HAVE_TRUNCF
  235. return truncf(x);
  236. #else
  237. return (float)SDL_trunc((double)x);
  238. #endif
  239. }
  240. double
  241. SDL_fmod(double x, double y)
  242. {
  243. #ifdef HAVE_FMOD
  244. return fmod(x, y);
  245. #else
  246. return SDL_uclibc_fmod(x, y);
  247. #endif
  248. }
  249. float SDL_fmodf(float x, float y)
  250. {
  251. #ifdef HAVE_FMODF
  252. return fmodf(x, y);
  253. #else
  254. return (float)SDL_fmod((double)x, (double)y);
  255. #endif
  256. }
  257. double
  258. SDL_log(double x)
  259. {
  260. #ifdef HAVE_LOG
  261. return log(x);
  262. #else
  263. return SDL_uclibc_log(x);
  264. #endif
  265. }
  266. float SDL_logf(float x)
  267. {
  268. #ifdef HAVE_LOGF
  269. return logf(x);
  270. #else
  271. return (float)SDL_log((double)x);
  272. #endif
  273. }
  274. double
  275. SDL_log10(double x)
  276. {
  277. #ifdef HAVE_LOG10
  278. return log10(x);
  279. #else
  280. return SDL_uclibc_log10(x);
  281. #endif
  282. }
  283. float SDL_log10f(float x)
  284. {
  285. #ifdef HAVE_LOG10F
  286. return log10f(x);
  287. #else
  288. return (float)SDL_log10((double)x);
  289. #endif
  290. }
  291. double
  292. SDL_modf(double x, double *y)
  293. {
  294. #ifdef HAVE_MODF
  295. return modf(x, y);
  296. #else
  297. return SDL_uclibc_modf(x, y);
  298. #endif
  299. }
  300. float SDL_modff(float x, float *y)
  301. {
  302. #ifdef HAVE_MODFF
  303. return modff(x, y);
  304. #else
  305. double double_result, double_y;
  306. double_result = SDL_modf((double)x, &double_y);
  307. *y = (float)double_y;
  308. return (float)double_result;
  309. #endif
  310. }
  311. double
  312. SDL_pow(double x, double y)
  313. {
  314. #ifdef HAVE_POW
  315. return pow(x, y);
  316. #else
  317. return SDL_uclibc_pow(x, y);
  318. #endif
  319. }
  320. float SDL_powf(float x, float y)
  321. {
  322. #ifdef HAVE_POWF
  323. return powf(x, y);
  324. #else
  325. return (float)SDL_pow((double)x, (double)y);
  326. #endif
  327. }
  328. double
  329. SDL_round(double arg)
  330. {
  331. #if defined HAVE_ROUND
  332. return round(arg);
  333. #else
  334. if (arg >= 0.0) {
  335. return SDL_floor(arg + 0.5);
  336. } else {
  337. return SDL_ceil(arg - 0.5);
  338. }
  339. #endif
  340. }
  341. float SDL_roundf(float arg)
  342. {
  343. #if defined HAVE_ROUNDF
  344. return roundf(arg);
  345. #else
  346. return (float)SDL_round((double)arg);
  347. #endif
  348. }
  349. long SDL_lround(double arg)
  350. {
  351. #if defined HAVE_LROUND
  352. return lround(arg);
  353. #else
  354. return (long)SDL_round(arg);
  355. #endif
  356. }
  357. long SDL_lroundf(float arg)
  358. {
  359. #if defined HAVE_LROUNDF
  360. return lroundf(arg);
  361. #else
  362. return (long)SDL_round((double)arg);
  363. #endif
  364. }
  365. double
  366. SDL_scalbn(double x, int n)
  367. {
  368. #ifdef HAVE_SCALBN
  369. return scalbn(x, n);
  370. #elif defined(HAVE__SCALB)
  371. return _scalb(x, n);
  372. #elif defined(HAVE_LIBC) && defined(HAVE_FLOAT_H) && (FLT_RADIX == 2)
  373. /* from scalbn(3): If FLT_RADIX equals 2 (which is
  374. * usual), then scalbn() is equivalent to ldexp(3). */
  375. return ldexp(x, n);
  376. #else
  377. return SDL_uclibc_scalbn(x, n);
  378. #endif
  379. }
  380. float SDL_scalbnf(float x, int n)
  381. {
  382. #ifdef HAVE_SCALBNF
  383. return scalbnf(x, n);
  384. #else
  385. return (float)SDL_scalbn((double)x, n);
  386. #endif
  387. }
  388. double
  389. SDL_sin(double x)
  390. {
  391. #ifdef HAVE_SIN
  392. return sin(x);
  393. #else
  394. return SDL_uclibc_sin(x);
  395. #endif
  396. }
  397. float SDL_sinf(float x)
  398. {
  399. #ifdef HAVE_SINF
  400. return sinf(x);
  401. #else
  402. return (float)SDL_sin((double)x);
  403. #endif
  404. }
  405. double
  406. SDL_sqrt(double x)
  407. {
  408. #ifdef HAVE_SQRT
  409. return sqrt(x);
  410. #else
  411. return SDL_uclibc_sqrt(x);
  412. #endif
  413. }
  414. float SDL_sqrtf(float x)
  415. {
  416. #ifdef HAVE_SQRTF
  417. return sqrtf(x);
  418. #else
  419. return (float)SDL_sqrt((double)x);
  420. #endif
  421. }
  422. double
  423. SDL_tan(double x)
  424. {
  425. #ifdef HAVE_TAN
  426. return tan(x);
  427. #else
  428. return SDL_uclibc_tan(x);
  429. #endif
  430. }
  431. float SDL_tanf(float x)
  432. {
  433. #ifdef HAVE_TANF
  434. return tanf(x);
  435. #else
  436. return (float)SDL_tan((double)x);
  437. #endif
  438. }
  439. int SDL_abs(int x)
  440. {
  441. #ifdef HAVE_ABS
  442. return abs(x);
  443. #else
  444. return (x < 0) ? -x : x;
  445. #endif
  446. }
  447. #ifdef HAVE_CTYPE_H
  448. int SDL_isalpha(int x)
  449. {
  450. return isalpha(x);
  451. }
  452. int SDL_isalnum(int x) { return isalnum(x); }
  453. int SDL_isdigit(int x) { return isdigit(x); }
  454. int SDL_isxdigit(int x) { return isxdigit(x); }
  455. int SDL_ispunct(int x) { return ispunct(x); }
  456. int SDL_isspace(int x) { return isspace(x); }
  457. int SDL_isupper(int x) { return isupper(x); }
  458. int SDL_islower(int x) { return islower(x); }
  459. int SDL_isprint(int x) { return isprint(x); }
  460. int SDL_isgraph(int x) { return isgraph(x); }
  461. int SDL_iscntrl(int x) { return iscntrl(x); }
  462. int SDL_toupper(int x) { return toupper(x); }
  463. int SDL_tolower(int x) { return tolower(x); }
  464. #else
  465. int SDL_isalpha(int x)
  466. {
  467. return (SDL_isupper(x)) || (SDL_islower(x));
  468. }
  469. int SDL_isalnum(int x) { return (SDL_isalpha(x)) || (SDL_isdigit(x)); }
  470. int SDL_isdigit(int x) { return ((x) >= '0') && ((x) <= '9'); }
  471. int SDL_isxdigit(int x) { return (((x) >= 'A') && ((x) <= 'F')) || (((x) >= 'a') && ((x) <= 'f')) || (SDL_isdigit(x)); }
  472. int SDL_ispunct(int x) { return (SDL_isgraph(x)) && (!SDL_isalnum(x)); }
  473. int SDL_isspace(int x) { return ((x) == ' ') || ((x) == '\t') || ((x) == '\r') || ((x) == '\n') || ((x) == '\f') || ((x) == '\v'); }
  474. int SDL_isupper(int x) { return ((x) >= 'A') && ((x) <= 'Z'); }
  475. int SDL_islower(int x) { return ((x) >= 'a') && ((x) <= 'z'); }
  476. int SDL_isprint(int x) { return ((x) >= ' ') && ((x) < '\x7f'); }
  477. int SDL_isgraph(int x) { return (SDL_isprint(x)) && ((x) != ' '); }
  478. int SDL_iscntrl(int x) { return (((x) >= '\0') && ((x) <= '\x1f')) || ((x) == '\x7f'); }
  479. int SDL_toupper(int x) { return ((x) >= 'a') && ((x) <= 'z') ? ('A' + ((x) - 'a')) : (x); }
  480. int SDL_tolower(int x) { return ((x) >= 'A') && ((x) <= 'Z') ? ('a' + ((x) - 'A')) : (x); }
  481. #endif
  482. /* This file contains a portable memcpy manipulation function for SDL */
  483. void *SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len)
  484. {
  485. #ifdef __GNUC__
  486. /* Presumably this is well tuned for speed.
  487. On my machine this is twice as fast as the C code below.
  488. */
  489. return __builtin_memcpy(dst, src, len);
  490. #elif defined(HAVE_MEMCPY)
  491. return memcpy(dst, src, len);
  492. #elif defined(HAVE_BCOPY)
  493. bcopy(src, dst, len);
  494. return dst;
  495. #else
  496. /* GCC 4.9.0 with -O3 will generate movaps instructions with the loop
  497. using Uint32* pointers, so we need to make sure the pointers are
  498. aligned before we loop using them.
  499. */
  500. if (((uintptr_t)src & 0x3) || ((uintptr_t)dst & 0x3)) {
  501. /* Do an unaligned byte copy */
  502. Uint8 *srcp1 = (Uint8 *)src;
  503. Uint8 *dstp1 = (Uint8 *)dst;
  504. while (len--) {
  505. *dstp1++ = *srcp1++;
  506. }
  507. } else {
  508. size_t left = (len % 4);
  509. Uint32 *srcp4, *dstp4;
  510. Uint8 *srcp1, *dstp1;
  511. srcp4 = (Uint32 *)src;
  512. dstp4 = (Uint32 *)dst;
  513. len /= 4;
  514. while (len--) {
  515. *dstp4++ = *srcp4++;
  516. }
  517. srcp1 = (Uint8 *)srcp4;
  518. dstp1 = (Uint8 *)dstp4;
  519. switch (left) {
  520. case 3:
  521. *dstp1++ = *srcp1++;
  522. case 2:
  523. *dstp1++ = *srcp1++;
  524. case 1:
  525. *dstp1++ = *srcp1++;
  526. }
  527. }
  528. return dst;
  529. #endif /* __GNUC__ */
  530. }
  531. void *SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len)
  532. {
  533. #ifdef HAVE_MEMSET
  534. return memset(dst, c, len);
  535. #else
  536. size_t left;
  537. Uint32 *dstp4;
  538. Uint8 *dstp1 = (Uint8 *)dst;
  539. Uint8 value1;
  540. Uint32 value4;
  541. /* The value used in memset() is a byte, passed as an int */
  542. c &= 0xff;
  543. /* The destination pointer needs to be aligned on a 4-byte boundary to
  544. * execute a 32-bit set. Set first bytes manually if needed until it is
  545. * aligned. */
  546. value1 = (Uint8)c;
  547. while ((uintptr_t)dstp1 & 0x3) {
  548. if (len--) {
  549. *dstp1++ = value1;
  550. } else {
  551. return dst;
  552. }
  553. }
  554. value4 = ((Uint32)c | ((Uint32)c << 8) | ((Uint32)c << 16) | ((Uint32)c << 24));
  555. dstp4 = (Uint32 *)dstp1;
  556. left = (len % 4);
  557. len /= 4;
  558. while (len--) {
  559. *dstp4++ = value4;
  560. }
  561. dstp1 = (Uint8 *)dstp4;
  562. switch (left) {
  563. case 3:
  564. *dstp1++ = value1;
  565. case 2:
  566. *dstp1++ = value1;
  567. case 1:
  568. *dstp1++ = value1;
  569. }
  570. return dst;
  571. #endif /* HAVE_MEMSET */
  572. }
  573. /* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
  574. void *SDL_memset4(void *dst, Uint32 val, size_t dwords)
  575. {
  576. #if defined(__APPLE__) && defined(HAVE_STRING_H)
  577. memset_pattern4(dst, &val, dwords * 4);
  578. #elif defined(__GNUC__) && defined(__i386__)
  579. int u0, u1, u2;
  580. __asm__ __volatile__(
  581. "cld \n\t"
  582. "rep ; stosl \n\t"
  583. : "=&D"(u0), "=&a"(u1), "=&c"(u2)
  584. : "0"(dst), "1"(val), "2"(SDL_static_cast(Uint32, dwords))
  585. : "memory");
  586. #else
  587. size_t _n = (dwords + 3) / 4;
  588. Uint32 *_p = SDL_static_cast(Uint32 *, dst);
  589. Uint32 _val = (val);
  590. if (dwords == 0) {
  591. return dst;
  592. }
  593. switch (dwords % 4) {
  594. case 0:
  595. do {
  596. *_p++ = _val;
  597. SDL_FALLTHROUGH;
  598. case 3:
  599. *_p++ = _val;
  600. SDL_FALLTHROUGH;
  601. case 2:
  602. *_p++ = _val;
  603. SDL_FALLTHROUGH;
  604. case 1:
  605. *_p++ = _val;
  606. } while (--_n);
  607. }
  608. #endif
  609. return dst;
  610. }
  611. #if defined(HAVE_CTYPE_H) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
  612. int SDL_isblank(int x)
  613. {
  614. return isblank(x);
  615. }
  616. #else
  617. int SDL_isblank(int x)
  618. {
  619. return ((x) == ' ') || ((x) == '\t');
  620. }
  621. #endif
  622. void *SDL_aligned_alloc(size_t alignment, size_t size)
  623. {
  624. size_t padding;
  625. Uint8 *retval = NULL;
  626. if (alignment < sizeof(void*)) {
  627. alignment = sizeof(void*);
  628. }
  629. padding = (alignment - (size % alignment));
  630. if (SDL_size_add_overflow(size, alignment, &size) == 0 &&
  631. SDL_size_add_overflow(size, sizeof(void *), &size) == 0 &&
  632. SDL_size_add_overflow(size, padding, &size) == 0) {
  633. void *original = SDL_malloc(size);
  634. if (original) {
  635. /* Make sure we have enough space to store the original pointer */
  636. retval = (Uint8 *)original + sizeof(original);
  637. /* Align the pointer we're going to return */
  638. retval += alignment - (((size_t)retval) % alignment);
  639. /* Store the original pointer right before the returned value */
  640. SDL_memcpy(retval - sizeof(original), &original, sizeof(original));
  641. }
  642. }
  643. return retval;
  644. }
  645. void SDL_aligned_free(void *mem)
  646. {
  647. if (mem) {
  648. void *original;
  649. SDL_memcpy(&original, ((Uint8 *)mem - sizeof(original)), sizeof(original));
  650. SDL_free(original);
  651. }
  652. }