test-fenvinline.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /* Test for fenv inline implementations.
  2. Copyright (C) 2015-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. #ifndef _GNU_SOURCE
  16. # define _GNU_SOURCE
  17. #endif
  18. /* To make sure the fenv inline function are used. */
  19. #undef __NO_MATH_INLINES
  20. #include <fenv.h>
  21. #include <stdio.h>
  22. #include <math-tests.h>
  23. /*
  24. Since not all architectures might define all exceptions, we define
  25. a private set and map accordingly.
  26. */
  27. #define NO_EXC 0
  28. #define INEXACT_EXC 0x1
  29. #define DIVBYZERO_EXC 0x2
  30. #define UNDERFLOW_EXC 0x04
  31. #define OVERFLOW_EXC 0x08
  32. #define INVALID_EXC 0x10
  33. #define ALL_EXC \
  34. (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \
  35. INVALID_EXC)
  36. static int count_errors;
  37. #if FE_ALL_EXCEPT
  38. static void
  39. test_single_exception_fp_int (int exception,
  40. int exc_flag,
  41. int fe_flag,
  42. const char *flag_name)
  43. {
  44. if (exception & exc_flag)
  45. {
  46. if (fetestexcept (fe_flag))
  47. printf (" Pass: Exception \"%s\" is set\n", flag_name);
  48. else
  49. {
  50. printf (" Fail: Exception \"%s\" is not set\n", flag_name);
  51. ++count_errors;
  52. }
  53. }
  54. else
  55. {
  56. if (fetestexcept (fe_flag))
  57. {
  58. printf (" Fail: Exception \"%s\" is set\n", flag_name);
  59. ++count_errors;
  60. }
  61. else
  62. printf (" Pass: Exception \"%s\" is not set\n", flag_name);
  63. }
  64. }
  65. /* Test whether a given exception was raised. */
  66. static void
  67. test_single_exception_fp_double (int exception,
  68. int exc_flag,
  69. double fe_flag,
  70. const char *flag_name)
  71. {
  72. if (exception & exc_flag)
  73. {
  74. if (fetestexcept (fe_flag))
  75. printf (" Pass: Exception \"%s\" is set\n", flag_name);
  76. else
  77. {
  78. printf (" Fail: Exception \"%s\" is not set\n", flag_name);
  79. ++count_errors;
  80. }
  81. }
  82. else
  83. {
  84. if (fetestexcept (fe_flag))
  85. {
  86. printf (" Fail: Exception \"%s\" is set\n", flag_name);
  87. ++count_errors;
  88. }
  89. else
  90. printf (" Pass: Exception \"%s\" is not set\n", flag_name);
  91. }
  92. }
  93. #endif
  94. static void
  95. test_exceptions (const char *test_name, int exception)
  96. {
  97. printf ("Test: %s\n", test_name);
  98. #ifdef FE_DIVBYZERO
  99. test_single_exception_fp_double (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
  100. "DIVBYZERO");
  101. #endif
  102. #ifdef FE_INVALID
  103. test_single_exception_fp_double (exception, INVALID_EXC, FE_INVALID,
  104. "INVALID");
  105. #endif
  106. #ifdef FE_INEXACT
  107. test_single_exception_fp_double (exception, INEXACT_EXC, FE_INEXACT,
  108. "INEXACT");
  109. #endif
  110. #ifdef FE_UNDERFLOW
  111. test_single_exception_fp_double (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
  112. "UNDERFLOW");
  113. #endif
  114. #ifdef FE_OVERFLOW
  115. test_single_exception_fp_double (exception, OVERFLOW_EXC, FE_OVERFLOW,
  116. "OVERFLOW");
  117. #endif
  118. }
  119. static void
  120. test_exceptionflag (void)
  121. {
  122. printf ("Test: fegetexceptionflag (FE_ALL_EXCEPT)\n");
  123. #if FE_ALL_EXCEPT
  124. fexcept_t excepts;
  125. feclearexcept (FE_ALL_EXCEPT);
  126. feraiseexcept (FE_INVALID);
  127. fegetexceptflag (&excepts, FE_ALL_EXCEPT);
  128. feclearexcept (FE_ALL_EXCEPT);
  129. feraiseexcept (FE_OVERFLOW | FE_INEXACT);
  130. fesetexceptflag (&excepts, FE_ALL_EXCEPT);
  131. test_single_exception_fp_int (INVALID_EXC, INVALID_EXC, FE_INVALID,
  132. "INVALID (int)");
  133. test_single_exception_fp_int (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
  134. "OVERFLOW (int)");
  135. test_single_exception_fp_int (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
  136. "INEXACT (int)");
  137. /* Same test, but using double as argument */
  138. feclearexcept (FE_ALL_EXCEPT);
  139. feraiseexcept (FE_INVALID);
  140. fegetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
  141. feclearexcept (FE_ALL_EXCEPT);
  142. feraiseexcept (FE_OVERFLOW | FE_INEXACT);
  143. fesetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
  144. test_single_exception_fp_double (INVALID_EXC, INVALID_EXC, FE_INVALID,
  145. "INVALID (double)");
  146. test_single_exception_fp_double (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
  147. "OVERFLOW (double)");
  148. test_single_exception_fp_double (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
  149. "INEXACT (double)");
  150. #endif
  151. }
  152. static void
  153. test_fesetround (void)
  154. {
  155. #if defined FE_TONEAREST && defined FE_TOWARDZERO
  156. int res1;
  157. int res2;
  158. printf ("Tests for fesetround\n");
  159. /* The fesetround should not itself cause the test to fail, however it
  160. should either succeed for both 'int' and 'double' argument, or fail
  161. for both. */
  162. res1 = fesetround ((int) FE_TOWARDZERO);
  163. res2 = fesetround ((double) FE_TOWARDZERO);
  164. if (res1 != res2)
  165. {
  166. printf ("fesetround (FE_TOWARDZERO) failed: %d, %d\n", res1, res2);
  167. ++count_errors;
  168. }
  169. res1 = fesetround ((int) FE_TONEAREST);
  170. res2 = fesetround ((double) FE_TONEAREST);
  171. if (res1 != res2)
  172. {
  173. printf ("fesetround (FE_TONEAREST) failed: %d, %d\n", res1, res2);
  174. ++count_errors;
  175. }
  176. #endif
  177. }
  178. #if FE_ALL_EXCEPT
  179. /* Tests for feenableexcept/fedisableexcept. */
  180. static void
  181. feenable_test (const char *flag_name, fexcept_t fe_exc)
  182. {
  183. int fe_exci = fe_exc;
  184. double fe_excd = fe_exc;
  185. int excepts;
  186. /* First disable all exceptions. */
  187. if (fedisableexcept (FE_ALL_EXCEPT) == -1)
  188. {
  189. printf ("Test: fedisableexcept (FE_ALL_EXCEPT) failed\n");
  190. ++count_errors;
  191. /* If this fails, the other tests don't make sense. */
  192. return;
  193. }
  194. /* Test for inline macros using integer argument. */
  195. excepts = feenableexcept (fe_exci);
  196. if (!EXCEPTION_ENABLE_SUPPORTED (fe_exci) && excepts == -1)
  197. {
  198. printf ("Test: not testing feenableexcept, it isn't implemented.\n");
  199. return;
  200. }
  201. if (excepts == -1)
  202. {
  203. printf ("Test: feenableexcept (%s) failed\n", flag_name);
  204. ++count_errors;
  205. return;
  206. }
  207. if (excepts != 0)
  208. {
  209. printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
  210. flag_name, excepts);
  211. ++count_errors;
  212. }
  213. /* And now disable the exception again. */
  214. excepts = fedisableexcept (fe_exc);
  215. if (excepts == -1)
  216. {
  217. printf ("Test: fedisableexcept (%s) failed\n", flag_name);
  218. ++count_errors;
  219. return;
  220. }
  221. if (excepts != fe_exc)
  222. {
  223. printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
  224. flag_name, (unsigned int)fe_exc, excepts);
  225. ++count_errors;
  226. }
  227. /* Test for inline macros using double argument. */
  228. excepts = feenableexcept (fe_excd);
  229. if (!EXCEPTION_ENABLE_SUPPORTED (fe_excd) && excepts == -1)
  230. {
  231. printf ("Test: not testing feenableexcept, it isn't implemented.\n");
  232. return;
  233. }
  234. if (excepts == -1)
  235. {
  236. printf ("Test: feenableexcept (%s) failed\n", flag_name);
  237. ++count_errors;
  238. return;
  239. }
  240. if (excepts != 0)
  241. {
  242. printf ("Test: feenableexcept (%s) failed, return should be 0, is %x\n",
  243. flag_name, excepts);
  244. ++count_errors;
  245. }
  246. /* And now disable the exception again. */
  247. excepts = fedisableexcept (fe_exc);
  248. if (excepts == -1)
  249. {
  250. printf ("Test: fedisableexcept (%s) failed\n", flag_name);
  251. ++count_errors;
  252. return;
  253. }
  254. if (excepts != fe_exc)
  255. {
  256. printf ("Test: fedisableexcept (%s) failed, return should be 0x%x, is 0x%x\n",
  257. flag_name, (unsigned int)fe_exc, excepts);
  258. ++count_errors;
  259. }
  260. }
  261. #endif
  262. static void
  263. test_feenabledisable (void)
  264. {
  265. printf ("Tests for feenableexcepts/fedisableexcept\n");
  266. /* We might have some exceptions still set. */
  267. feclearexcept (FE_ALL_EXCEPT);
  268. #ifdef FE_DIVBYZERO
  269. feenable_test ("FE_DIVBYZERO", FE_DIVBYZERO);
  270. #endif
  271. #ifdef FE_INVALID
  272. feenable_test ("FE_INVALID", FE_INVALID);
  273. #endif
  274. #ifdef FE_INEXACT
  275. feenable_test ("FE_INEXACT", FE_INEXACT);
  276. #endif
  277. #ifdef FE_UNDERFLOW
  278. feenable_test ("FE_UNDERFLOW", FE_UNDERFLOW);
  279. #endif
  280. #ifdef FE_OVERFLOW
  281. feenable_test ("FE_OVERFLOW", FE_OVERFLOW);
  282. #endif
  283. fesetenv (FE_DFL_ENV);
  284. }
  285. static int
  286. do_test (void)
  287. {
  288. /* clear all exceptions and test if all are cleared */
  289. feclearexcept (FE_ALL_EXCEPT);
  290. test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
  291. NO_EXC);
  292. /* raise all exceptions and test if all are raised */
  293. feraiseexcept (FE_ALL_EXCEPT);
  294. if (EXCEPTION_TESTS (float))
  295. test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
  296. ALL_EXC);
  297. /* Same test, but using double as argument */
  298. feclearexcept ((double)FE_ALL_EXCEPT);
  299. test_exceptions ("feclearexcept ((double)FE_ALL_EXCEPT) clears all exceptions",
  300. NO_EXC);
  301. feraiseexcept ((double)FE_ALL_EXCEPT);
  302. if (EXCEPTION_TESTS (float))
  303. test_exceptions ("feraiseexcept ((double)FE_ALL_EXCEPT) raises all exceptions",
  304. ALL_EXC);
  305. if (EXCEPTION_TESTS (float))
  306. test_exceptionflag ();
  307. test_fesetround ();
  308. test_feenabledisable ();
  309. return count_errors;
  310. }
  311. #define TEST_FUNCTION do_test ()
  312. #include "../test-skeleton.c"