remquoq.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* Compute remainder and a congruent to the quotient.
  2. Copyright (C) 1997, 1999, 2002 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
  5. Jakub Jelinek <jj@ultra.linux.cz>, 1999.
  6. The GNU C Library is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Lesser General Public
  8. License as published by the Free Software Foundation; either
  9. version 2.1 of the License, or (at your option) any later version.
  10. The GNU C Library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public
  15. License along with the GNU C Library; if not, write to the Free
  16. Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  17. 02111-1307 USA. */
  18. #include "quadmath-imp.h"
  19. static const __float128 zero = 0.0;
  20. __float128
  21. remquoq (__float128 x, __float128 y, int *quo)
  22. {
  23. int64_t hx,hy;
  24. uint64_t sx,lx,ly,qs;
  25. int cquo;
  26. GET_FLT128_WORDS64 (hx, lx, x);
  27. GET_FLT128_WORDS64 (hy, ly, y);
  28. sx = hx & 0x8000000000000000ULL;
  29. qs = sx ^ (hy & 0x8000000000000000ULL);
  30. hy &= 0x7fffffffffffffffLL;
  31. hx &= 0x7fffffffffffffffLL;
  32. /* Purge off exception values. */
  33. if ((hy | ly) == 0)
  34. return (x * y) / (x * y); /* y = 0 */
  35. if ((hx >= 0x7fff000000000000LL) /* x not finite */
  36. || ((hy >= 0x7fff000000000000LL) /* y is NaN */
  37. && (((hy - 0x7fff000000000000LL) | ly) != 0)))
  38. return (x * y) / (x * y);
  39. if (hy <= 0x7ffbffffffffffffLL)
  40. x = fmodq (x, 8 * y); /* now x < 8y */
  41. if (((hx - hy) | (lx - ly)) == 0)
  42. {
  43. *quo = qs ? -1 : 1;
  44. return zero * x;
  45. }
  46. x = fabsq (x);
  47. y = fabsq (y);
  48. cquo = 0;
  49. if (x >= 4 * y)
  50. {
  51. x -= 4 * y;
  52. cquo += 4;
  53. }
  54. if (x >= 2 * y)
  55. {
  56. x -= 2 * y;
  57. cquo += 2;
  58. }
  59. if (hy < 0x0002000000000000LL)
  60. {
  61. if (x + x > y)
  62. {
  63. x -= y;
  64. ++cquo;
  65. if (x + x >= y)
  66. {
  67. x -= y;
  68. ++cquo;
  69. }
  70. }
  71. }
  72. else
  73. {
  74. __float128 y_half = 0.5Q * y;
  75. if (x > y_half)
  76. {
  77. x -= y;
  78. ++cquo;
  79. if (x >= y_half)
  80. {
  81. x -= y;
  82. ++cquo;
  83. }
  84. }
  85. }
  86. *quo = qs ? -cquo : cquo;
  87. if (sx)
  88. x = -x;
  89. return x;
  90. }