efgcvt.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* Compatibility functions for floating point formatting.
  2. Copyright (C) 1995-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <math.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <sys/param.h>
  19. #include <float.h>
  20. #include <libc-lock.h>
  21. #include <math_ldbl_opt.h>
  22. #ifndef FLOAT_TYPE
  23. # define FLOAT_TYPE double
  24. # define FUNC_PREFIX
  25. # define FLOAT_FMT_FLAG
  26. /* Actually we have to write (DBL_DIG + log10 (DBL_MAX_10_EXP)) but we
  27. don't have log10 available in the preprocessor. */
  28. # define MAXDIG (NDIGIT_MAX + 3)
  29. # define FCVT_MAXDIG (DBL_MAX_10_EXP + MAXDIG)
  30. # if DBL_MANT_DIG == 53
  31. # define NDIGIT_MAX 17
  32. # elif DBL_MANT_DIG == 24
  33. # define NDIGIT_MAX 9
  34. # elif DBL_MANT_DIG == 56
  35. # define NDIGIT_MAX 18
  36. # else
  37. /* See IEEE 854 5.6, table 2 for this formula. Unfortunately we need a
  38. compile time constant here, so we cannot use it. */
  39. # error "NDIGIT_MAX must be precomputed"
  40. # define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0)))
  41. # endif
  42. #else
  43. # define LONG_DOUBLE_CVT
  44. #endif
  45. #define APPEND(a, b) APPEND2 (a, b)
  46. #define APPEND2(a, b) a##b
  47. #define __APPEND(a, b) __APPEND2 (a, b)
  48. #define __APPEND2(a, b) __##a##b
  49. #define FCVT_BUFFER APPEND (FUNC_PREFIX, fcvt_buffer)
  50. #define FCVT_BUFPTR APPEND (FUNC_PREFIX, fcvt_bufptr)
  51. #define ECVT_BUFFER APPEND (FUNC_PREFIX, ecvt_buffer)
  52. static char FCVT_BUFFER[MAXDIG];
  53. static char ECVT_BUFFER[MAXDIG];
  54. libc_freeres_ptr (static char *FCVT_BUFPTR);
  55. char *
  56. __APPEND (FUNC_PREFIX, fcvt) (FLOAT_TYPE value, int ndigit, int *decpt,
  57. int *sign)
  58. {
  59. if (FCVT_BUFPTR == NULL)
  60. {
  61. if (__APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign,
  62. FCVT_BUFFER, MAXDIG) != -1)
  63. return FCVT_BUFFER;
  64. FCVT_BUFPTR = (char *) malloc (FCVT_MAXDIG);
  65. if (FCVT_BUFPTR == NULL)
  66. return FCVT_BUFFER;
  67. }
  68. (void) __APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign,
  69. FCVT_BUFPTR, FCVT_MAXDIG);
  70. return FCVT_BUFPTR;
  71. }
  72. char *
  73. __APPEND (FUNC_PREFIX, ecvt) (FLOAT_TYPE value, int ndigit, int *decpt,
  74. int *sign)
  75. {
  76. (void) __APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign,
  77. ECVT_BUFFER, MAXDIG);
  78. return ECVT_BUFFER;
  79. }
  80. char *
  81. __APPEND (FUNC_PREFIX, gcvt) (FLOAT_TYPE value, int ndigit, char *buf)
  82. {
  83. sprintf (buf, "%.*" FLOAT_FMT_FLAG "g", MIN (ndigit, NDIGIT_MAX), value);
  84. return buf;
  85. }
  86. #if LONG_DOUBLE_COMPAT (libc, GLIBC_2_0)
  87. # ifdef LONG_DOUBLE_CVT
  88. # define cvt_symbol(symbol) \
  89. cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
  90. APPEND (FUNC_PREFIX, symbol), GLIBC_2_4)
  91. # define cvt_symbol_1(lib, local, symbol, version) \
  92. versioned_symbol (lib, local, symbol, version)
  93. # else
  94. # define cvt_symbol(symbol) \
  95. cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
  96. APPEND (q, symbol), GLIBC_2_0); \
  97. strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
  98. # define cvt_symbol_1(lib, local, symbol, version) \
  99. compat_symbol (lib, local, symbol, version)
  100. # endif
  101. #else
  102. # define cvt_symbol(symbol) \
  103. strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
  104. #endif
  105. cvt_symbol(fcvt);
  106. cvt_symbol(ecvt);
  107. cvt_symbol(gcvt);