fmodf.c 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /*****************************************************************************/
  2. /*****************************************************************************/
  3. // fmodf from musl-0.9.15
  4. /*****************************************************************************/
  5. /*****************************************************************************/
  6. #include "libm.h"
  7. float fmodf(float x, float y)
  8. {
  9. union {float f; uint32_t i;} ux = {x}, uy = {y};
  10. int ex = ux.i>>23 & 0xff;
  11. int ey = uy.i>>23 & 0xff;
  12. uint32_t sx = ux.i & 0x80000000;
  13. uint32_t i;
  14. uint32_t uxi = ux.i;
  15. if (uy.i<<1 == 0 || isnan(y) || ex == 0xff)
  16. return (x*y)/(x*y);
  17. if (uxi<<1 <= uy.i<<1) {
  18. if (uxi<<1 == uy.i<<1)
  19. return 0*x;
  20. return x;
  21. }
  22. /* normalize x and y */
  23. if (!ex) {
  24. for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1);
  25. uxi <<= -ex + 1;
  26. } else {
  27. uxi &= -1U >> 9;
  28. uxi |= 1U << 23;
  29. }
  30. if (!ey) {
  31. for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1);
  32. uy.i <<= -ey + 1;
  33. } else {
  34. uy.i &= -1U >> 9;
  35. uy.i |= 1U << 23;
  36. }
  37. /* x mod y */
  38. for (; ex > ey; ex--) {
  39. i = uxi - uy.i;
  40. if (i >> 31 == 0) {
  41. if (i == 0)
  42. return 0*x;
  43. uxi = i;
  44. }
  45. uxi <<= 1;
  46. }
  47. i = uxi - uy.i;
  48. if (i >> 31 == 0) {
  49. if (i == 0)
  50. return 0*x;
  51. uxi = i;
  52. }
  53. for (; uxi>>23 == 0; uxi <<= 1, ex--);
  54. /* scale result up */
  55. if (ex > 0) {
  56. uxi -= 1U << 23;
  57. uxi |= (uint32_t)ex << 23;
  58. } else {
  59. uxi >>= -ex + 1;
  60. }
  61. uxi |= sx;
  62. ux.i = uxi;
  63. return ux.f;
  64. }