gen-tst-strtod-round.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /* Generate table of tests in tst-strtod-round.c from
  2. tst-strtod-round-data.
  3. Copyright (C) 2012-2019 Free Software Foundation, Inc.
  4. This file is part of the GNU C Library.
  5. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. /* Compile this program as:
  17. gcc -std=gnu11 -O2 -Wall -Wextra gen-tst-strtod-round.c -lmpfr \
  18. -o gen-tst-strtod-round
  19. (use of current MPFR version recommended) and run it as:
  20. gen-tst-strtod-round tst-strtod-round-data tst-strtod-round-data.h
  21. The output file will be generated as tst-strtod-round-data.h
  22. */
  23. #define _GNU_SOURCE
  24. #include <assert.h>
  25. #include <stdbool.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <mpfr.h>
  30. /* Work around incorrect ternary value from mpfr_strtofr
  31. <https://sympa.inria.fr/sympa/arc/mpfr/2012-08/msg00005.html>. */
  32. #define WORKAROUND
  33. static int
  34. string_to_fp (mpfr_t f, const char *s, mpfr_rnd_t rnd)
  35. {
  36. mpfr_clear_overflow ();
  37. #ifdef WORKAROUND
  38. mpfr_t f2;
  39. mpfr_init2 (f2, 100000);
  40. int r0 = mpfr_strtofr (f2, s, NULL, 0, rnd);
  41. int r = mpfr_set (f, f2, rnd);
  42. r |= mpfr_subnormalize (f, r, rnd);
  43. mpfr_clear (f2);
  44. return r0 | r;
  45. #else
  46. int r = mpfr_strtofr (f, s, NULL, 0, rnd);
  47. r |= mpfr_subnormalize (f, r, rnd);
  48. return r;
  49. #endif
  50. }
  51. void
  52. print_fp (FILE *fout, mpfr_t f, const char *suffix)
  53. {
  54. if (mpfr_inf_p (f))
  55. mpfr_fprintf (fout, "\t%sINF%s", mpfr_signbit (f) ? "-" : "", suffix);
  56. else
  57. mpfr_fprintf (fout, "\t%Ra%s", f, suffix);
  58. }
  59. static void
  60. round_str (FILE *fout, const char *s, int prec, int emin, int emax,
  61. bool ibm_ld)
  62. {
  63. mpfr_t max_value;
  64. mpfr_t f;
  65. mpfr_set_default_prec (prec);
  66. mpfr_set_emin (emin);
  67. mpfr_set_emax (emax);
  68. mpfr_init (f);
  69. int r = string_to_fp (f, s, MPFR_RNDD);
  70. bool overflow = mpfr_overflow_p () != 0;
  71. if (ibm_ld)
  72. {
  73. assert (prec == 106 && emin == -1073 && emax == 1024);
  74. /* The maximum value in IBM long double has discontiguous
  75. mantissa bits. */
  76. mpfr_init2 (max_value, 107);
  77. mpfr_set_str (max_value, "0x1.fffffffffffff7ffffffffffffcp+1023", 0,
  78. MPFR_RNDN);
  79. if (mpfr_cmpabs (f, max_value) > 0)
  80. {
  81. r = 1;
  82. overflow = true;
  83. }
  84. }
  85. mpfr_fprintf (fout, "\t%s,\n", r ? "false" : "true");
  86. print_fp (fout, f, overflow ? ", true,\n" : ", false,\n");
  87. string_to_fp (f, s, MPFR_RNDN);
  88. overflow = (mpfr_overflow_p () != 0
  89. || (ibm_ld && mpfr_cmpabs (f, max_value) > 0));
  90. print_fp (fout, f, overflow ? ", true,\n" : ", false,\n");
  91. string_to_fp (f, s, MPFR_RNDZ);
  92. overflow = (mpfr_overflow_p () != 0
  93. || (ibm_ld && mpfr_cmpabs (f, max_value) > 0));
  94. print_fp (fout, f, overflow ? ", true,\n" : ", false,\n");
  95. string_to_fp (f, s, MPFR_RNDU);
  96. overflow = (mpfr_overflow_p () != 0
  97. || (ibm_ld && mpfr_cmpabs (f, max_value) > 0));
  98. print_fp (fout, f, overflow ? ", true" : ", false");
  99. mpfr_clear (f);
  100. if (ibm_ld)
  101. mpfr_clear (max_value);
  102. }
  103. static void
  104. round_for_all (FILE *fout, const char *s)
  105. {
  106. static const struct fmt {
  107. int prec;
  108. int emin;
  109. int emax;
  110. bool ibm_ld;
  111. } formats[] = {
  112. { 24, -148, 128, false },
  113. { 53, -1073, 1024, false },
  114. /* This is the Intel extended float format. */
  115. { 64, -16444, 16384, false },
  116. /* This is the Motorola extended float format. */
  117. { 64, -16445, 16384, false },
  118. { 106, -1073, 1024, true },
  119. { 113, -16493, 16384, false },
  120. };
  121. mpfr_fprintf (fout, " TEST (\"");
  122. const char *p;
  123. for (p = s; *p; p++)
  124. {
  125. fputc (*p, fout);
  126. if ((p - s) % 60 == 59 && p[1])
  127. mpfr_fprintf (fout, "\"\n\t\"");
  128. }
  129. mpfr_fprintf (fout, "\",\n");
  130. int i;
  131. int n_formats = sizeof (formats) / sizeof (formats[0]);
  132. for (i = 0; i < n_formats; i++)
  133. {
  134. round_str (fout, s, formats[i].prec, formats[i].emin,
  135. formats[i].emax, formats[i].ibm_ld);
  136. if (i < n_formats - 1)
  137. mpfr_fprintf (fout, ",\n");
  138. }
  139. mpfr_fprintf (fout, "),\n");
  140. }
  141. int
  142. main (int argc, char **argv)
  143. {
  144. char *p = NULL;
  145. size_t len;
  146. ssize_t nbytes;
  147. FILE *fin, *fout;
  148. char *fin_name, *fout_name;
  149. if (argc < 3)
  150. {
  151. fprintf (stderr, "Usage: %s <input> <output>\n", basename (argv[0]));
  152. return EXIT_FAILURE;
  153. }
  154. fin_name = argv[1];
  155. fout_name = argv[2];
  156. fin = fopen (fin_name, "r");
  157. if (fin == NULL)
  158. {
  159. perror ("Could not open input for reading");
  160. return EXIT_FAILURE;
  161. }
  162. fout = fopen (fout_name, "w");
  163. if (fout == NULL)
  164. {
  165. perror ("Could not open output for writing");
  166. return EXIT_FAILURE;
  167. }
  168. fprintf (fout, "/* This file was generated by %s from %s. */\n",
  169. __FILE__, fin_name);
  170. fputs ("static const struct test tests[] = {\n", fout);
  171. while ((nbytes = getline (&p, &len, fin)) != -1)
  172. {
  173. if (p[nbytes - 1] == '\n')
  174. p[nbytes - 1] = 0;
  175. round_for_all (fout, p);
  176. free (p);
  177. p = NULL;
  178. }
  179. fputs ("};\n", fout);
  180. return EXIT_SUCCESS;
  181. }