gen-fromfp-tests.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/python3
  2. # Expand test inputs for fromfp functions into text to edit into libm-test.inc.
  3. # Copyright (C) 2016-2019 Free Software Foundation, Inc.
  4. # This file is part of the GNU C Library.
  5. #
  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. #
  11. # The GNU C Library is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. # Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public
  17. # License along with the GNU C Library; if not, see
  18. # <http://www.gnu.org/licenses/>.
  19. # Take test inputs on stdin, in format:
  20. #
  21. # i <value>:width [int-value]
  22. #
  23. # for integer inputs, or
  24. #
  25. # t <value> <pos> <z> <a>
  26. #
  27. # for noninteger inputs, where <pos> is "a" for fractional part
  28. # between 0 and 0.5, "be" for 0.5 with even integer part, "bo" for 0.5
  29. # with odd integer part and "c" for between 0.5 and 1; <z> is the
  30. # value truncated towards zero, <a> is the value rounded away from
  31. # zero, both being in the form <value>:<width>. Width values are for
  32. # the smallest type that can hold the value; for positive values, this
  33. # is an unsigned type.
  34. #
  35. # Command-line argument is function to generate tests for. Any input
  36. # lines not of the above form are just passed through unchanged.
  37. #
  38. # Note that the output of this script forms the largest part of the
  39. # tests for the fromfp functions, but not the whole of those tests.
  40. import sys
  41. func = sys.argv[1]
  42. invalid_res = 'IGNORE, NO_INEXACT_EXCEPTION|INVALID_EXCEPTION|ERRNO_EDOM'
  43. exact_res = 'NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED'
  44. if func == 'fromfpx' or func == 'ufromfpx':
  45. inexact_res = 'INEXACT_EXCEPTION|ERRNO_UNCHANGED'
  46. else:
  47. inexact_res = exact_res
  48. unsigned = func.startswith('ufromfp')
  49. rm_list = ['FP_INT_UPWARD', 'FP_INT_DOWNWARD', 'FP_INT_TOWARDZERO',
  50. 'FP_INT_TONEARESTFROMZERO', 'FP_INT_TONEAREST']
  51. rm_away_pos = {'FP_INT_UPWARD': 'a',
  52. 'FP_INT_DOWNWARD': 'z',
  53. 'FP_INT_TOWARDZERO': 'z',
  54. 'FP_INT_TONEARESTFROMZERO': 'be',
  55. 'FP_INT_TONEAREST': 'bo'}
  56. rm_away_neg = {'FP_INT_UPWARD': 'z',
  57. 'FP_INT_DOWNWARD': 'a',
  58. 'FP_INT_TOWARDZERO': 'z',
  59. 'FP_INT_TONEARESTFROMZERO': 'be',
  60. 'FP_INT_TONEAREST': 'bo'}
  61. if unsigned:
  62. test_macro = 'TEST_fiu_U'
  63. else:
  64. test_macro = 'TEST_fiu_M'
  65. for line in sys.stdin:
  66. if line.startswith('i'):
  67. data = line.split()
  68. val_width = data[1]
  69. val, width = val_width.split(':')
  70. negative = val.startswith('-')
  71. if unsigned and negative:
  72. continue
  73. width = int(width)
  74. if not unsigned and not negative:
  75. width += 1
  76. width_list = [0, 1]
  77. if width > 2:
  78. width_list.append(width - 1)
  79. if width > 1 and width <= 64:
  80. width_list.append(width)
  81. if width < 64:
  82. width_list.append(width + 1)
  83. if width < 63:
  84. width_list.append(64)
  85. width_list = [(w, str(w)) for w in width_list]
  86. width_list.append((64, 'UINT_MAX'))
  87. for rm in rm_list:
  88. for we in width_list:
  89. w, ws = we
  90. if w < width:
  91. print(' %s (%s, %s, %s, %s, %s),' %
  92. (test_macro, func, val, rm, ws, invalid_res))
  93. else:
  94. print(' %s (%s, %s, %s, %s, %s, %s),' %
  95. (test_macro, func, val, rm, ws, val, exact_res))
  96. elif line.startswith('t'):
  97. data = line.split()
  98. val = data[1]
  99. pos = data[2]
  100. z, z_width = data[3].split(':')
  101. z_width = int(z_width)
  102. a, a_width = data[4].split(':')
  103. a_width = int(a_width)
  104. if unsigned and z.startswith('-'):
  105. continue
  106. negative = val.startswith('-')
  107. if negative:
  108. rm_away = rm_away_neg
  109. else:
  110. rm_away = rm_away_pos
  111. for rm in rm_list:
  112. if pos >= rm_away[rm]:
  113. res, width = a, a_width
  114. else:
  115. res, width = z, z_width
  116. if not unsigned and not negative and res != '0':
  117. width += 1
  118. width_list = [0, 1]
  119. if width > 2:
  120. width_list.append(width - 1)
  121. if width > 1 and width <= 64:
  122. width_list.append(width)
  123. if width < 64:
  124. width_list.append(width + 1)
  125. if width < 63:
  126. width_list.append(64)
  127. width_list = [(w, str(w)) for w in width_list]
  128. width_list.append((64, 'UINT_MAX'))
  129. for we in width_list:
  130. w, ws = we
  131. if w < width or (unsigned and res.startswith('-')):
  132. print(' %s (%s, %s, %s, %s, %s),' %
  133. (test_macro, func, val, rm, ws, invalid_res))
  134. else:
  135. print(' %s (%s, %s, %s, %s, %s, %s),' %
  136. (test_macro, func, val, rm, ws, res, inexact_res))
  137. else:
  138. print(line.rstrip())