s_rintl.c 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*-
  2. * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. */
  26. #include "cdefs-compat.h"
  27. //__FBSDID("$FreeBSD: src/lib/msun/src/s_rintl.c,v 1.5 2008/02/22 11:59:05 bde Exp $");
  28. #include <float.h>
  29. #include <openlibm.h>
  30. #include "fpmath.h"
  31. //VBS
  32. #include "math_private.h"
  33. #if LDBL_MAX_EXP != 0x4000
  34. /* We also require the usual bias, min exp and expsign packing. */
  35. #error "Unsupported long double format"
  36. #endif
  37. #define BIAS (LDBL_MAX_EXP - 1)
  38. static const float
  39. shift[2] = {
  40. #if LDBL_MANT_DIG == 64
  41. 0x1.0p63, -0x1.0p63
  42. #elif LDBL_MANT_DIG == 113
  43. 0x1.0p112, -0x1.0p112
  44. #else
  45. #error "Unsupported long double format"
  46. #endif
  47. };
  48. static const float zero[2] = { 0.0, -0.0 };
  49. DLLEXPORT long double
  50. rintl(long double x)
  51. {
  52. union IEEEl2bits u;
  53. u_int32_t expsign;
  54. int ex, sign;
  55. u.e = x;
  56. expsign = u.xbits.expsign;
  57. ex = expsign & 0x7fff;
  58. if (ex >= BIAS + LDBL_MANT_DIG - 1) {
  59. if (ex == BIAS + LDBL_MAX_EXP)
  60. return (x + x); /* Inf, NaN, or unsupported format */
  61. return (x); /* finite and already an integer */
  62. }
  63. sign = expsign >> 15;
  64. /*
  65. * The following code assumes that intermediate results are
  66. * evaluated in long double precision. If they are evaluated in
  67. * greater precision, double rounding may occur, and if they are
  68. * evaluated in less precision (as on i386), results will be
  69. * wildly incorrect.
  70. */
  71. x += shift[sign];
  72. x -= shift[sign];
  73. /*
  74. * If the result is +-0, then it must have the same sign as x, but
  75. * the above calculation doesn't always give this. Fix up the sign.
  76. */
  77. if (ex < BIAS && x == 0.0L)
  78. return (zero[sign]);
  79. return (x);
  80. }