ldtoa.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* $OpenBSD: ldtoa.c,v 1.1 2008/09/07 20:36:08 martynas Exp $ */
  2. /*-
  3. * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include <sys/types.h>
  28. #ifndef __vax__
  29. #include <sys/ieee.h>
  30. #endif /* !__vax__ */
  31. #include <float.h>
  32. #include <inttypes.h>
  33. #include <limits.h>
  34. #include <math.h>
  35. #include <stdlib.h>
  36. #include "gdtoaimp.h"
  37. #if (LDBL_MANT_DIG > DBL_MANT_DIG)
  38. /*
  39. * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
  40. * except that the floating point argument is passed by reference.
  41. * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
  42. * However, a long double could have a valid exponent of 9999, so we
  43. * use INT_MAX in ldtoa() instead.
  44. */
  45. char *
  46. __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
  47. char **rve)
  48. {
  49. FPI fpi = {
  50. LDBL_MANT_DIG, /* nbits */
  51. LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */
  52. LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */
  53. FLT_ROUNDS, /* rounding */
  54. #ifdef Sudden_Underflow /* unused, but correct anyway */
  55. 1
  56. #else
  57. 0
  58. #endif
  59. };
  60. int be, kind;
  61. char *ret;
  62. struct ieee_ext *p = (struct ieee_ext *)ld;
  63. uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
  64. void *vbits = bits;
  65. /*
  66. * gdtoa doesn't know anything about the sign of the number, so
  67. * if the number is negative, we need to swap rounding modes of
  68. * 2 (upwards) and 3 (downwards).
  69. */
  70. *sign = p->ext_sign;
  71. fpi.rounding ^= (fpi.rounding >> 1) & p->ext_sign;
  72. be = p->ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
  73. EXT_TO_ARRAY32(p, bits);
  74. switch (fpclassify(*ld)) {
  75. case FP_NORMAL:
  76. kind = STRTOG_Normal;
  77. #ifdef EXT_IMPLICIT_NBIT
  78. bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
  79. #endif /* EXT_IMPLICIT_NBIT */
  80. break;
  81. case FP_ZERO:
  82. kind = STRTOG_Zero;
  83. break;
  84. case FP_SUBNORMAL:
  85. kind = STRTOG_Denormal;
  86. be++;
  87. break;
  88. case FP_INFINITE:
  89. kind = STRTOG_Infinite;
  90. break;
  91. case FP_NAN:
  92. kind = STRTOG_NaN;
  93. break;
  94. default:
  95. abort();
  96. }
  97. ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
  98. if (*decpt == -32768)
  99. *decpt = INT_MAX;
  100. return ret;
  101. }
  102. #else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
  103. char *
  104. __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
  105. char **rve)
  106. {
  107. char *ret;
  108. ret = dtoa((double)*ld, mode, ndigits, decpt, sign, rve);
  109. if (*decpt == 9999)
  110. *decpt = INT_MAX;
  111. return ret;
  112. }
  113. #endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */