Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lp_test_arit.c 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /**************************************************************************
  2. *
  3. * Copyright 2011 VMware, Inc.
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sub license, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial portions
  16. * of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21. * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. *
  26. **************************************************************************/
  27. #include <limits.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include "util/u_pointer.h"
  31. #include "util/u_memory.h"
  32. #include "util/u_math.h"
  33. #include "gallivm/lp_bld.h"
  34. #include "gallivm/lp_bld_debug.h"
  35. #include "gallivm/lp_bld_init.h"
  36. #include "gallivm/lp_bld_arit.h"
  37. #include "lp_test.h"
  38. void
  39. write_tsv_header(FILE *fp)
  40. {
  41. fprintf(fp,
  42. "result\t"
  43. "format\n");
  44. fflush(fp);
  45. }
  46. typedef float (*unary_func_t)(float);
  47. /**
  48. * Describe a test case of one unary function.
  49. */
  50. struct unary_test_t
  51. {
  52. /*
  53. * Test name -- name of the mathematical function under test.
  54. */
  55. const char *name;
  56. LLVMValueRef
  57. (*builder)(struct lp_build_context *bld, LLVMValueRef a);
  58. /*
  59. * Reference (pure-C) function.
  60. */
  61. float
  62. (*ref)(float a);
  63. /*
  64. * Test values.
  65. */
  66. const float *values;
  67. unsigned num_values;
  68. /*
  69. * Required precision in bits.
  70. */
  71. double precision;
  72. };
  73. static float negf(float x)
  74. {
  75. return -x;
  76. }
  77. const float exp2_values[] = {
  78. -60,
  79. -4,
  80. -2,
  81. -1,
  82. -1e-007,
  83. 0,
  84. 1e-007,
  85. 0.01,
  86. 0.1,
  87. 0.9,
  88. 0.99,
  89. 1,
  90. 2,
  91. 4,
  92. 60
  93. };
  94. const float log2_values[] = {
  95. #if 0
  96. /*
  97. * Smallest denormalized number; meant just for experimentation, but not
  98. * validation.
  99. */
  100. 1.4012984643248171e-45,
  101. #endif
  102. 1e-007,
  103. 0.1,
  104. 0.5,
  105. 0.99,
  106. 1,
  107. 1.01,
  108. 1.1,
  109. 1.9,
  110. 1.99,
  111. 2,
  112. 4,
  113. 100000,
  114. 1e+018
  115. };
  116. static float rsqrtf(float x)
  117. {
  118. return 1.0/sqrt(x);
  119. }
  120. const float rsqrt_values[] = {
  121. -1, -1e-007,
  122. 1e-007, 1,
  123. -4, -1,
  124. 1, 4,
  125. -1e+035, -100000,
  126. 100000, 1e+035,
  127. };
  128. const float sincos_values[] = {
  129. -5*M_PI/4,
  130. -4*M_PI/4,
  131. -4*M_PI/4,
  132. -3*M_PI/4,
  133. -2*M_PI/4,
  134. -1*M_PI/4,
  135. 1*M_PI/4,
  136. 2*M_PI/4,
  137. 3*M_PI/4,
  138. 4*M_PI/4,
  139. 5*M_PI/4,
  140. };
  141. /*
  142. * Unary test cases.
  143. */
  144. static const struct unary_test_t
  145. unary_tests[] = {
  146. {"neg", &lp_build_negate, &negf, exp2_values, Elements(exp2_values), 20.0 },
  147. {"exp2", &lp_build_exp2, &exp2f, exp2_values, Elements(exp2_values), 20.0 },
  148. {"log2", &lp_build_log2, &log2f, log2_values, Elements(log2_values), 20.0 },
  149. {"exp", &lp_build_exp, &expf, exp2_values, Elements(exp2_values), 18.0 },
  150. {"log", &lp_build_log, &logf, log2_values, Elements(log2_values), 20.0 },
  151. {"rsqrt", &lp_build_rsqrt, &rsqrtf, rsqrt_values, Elements(rsqrt_values), 20.0 },
  152. {"sin", &lp_build_sin, &sinf, sincos_values, Elements(sincos_values), 20.0 },
  153. {"cos", &lp_build_cos, &cosf, sincos_values, Elements(sincos_values), 20.0 },
  154. };
  155. /*
  156. * Build LLVM function that exercises the unary operator builder.
  157. */
  158. static LLVMValueRef
  159. build_unary_test_func(struct gallivm_state *gallivm,
  160. LLVMModuleRef module,
  161. LLVMContextRef context,
  162. const struct unary_test_t *test)
  163. {
  164. struct lp_type type = lp_type_float_vec(32);
  165. LLVMTypeRef i32t = LLVMInt32TypeInContext(context);
  166. LLVMTypeRef f32t = LLVMFloatTypeInContext(context);
  167. LLVMTypeRef vf32t = lp_build_vec_type(gallivm, type);
  168. LLVMTypeRef args[1] = { f32t };
  169. LLVMValueRef func = LLVMAddFunction(module, test->name, LLVMFunctionType(f32t, args, Elements(args), 0));
  170. LLVMValueRef arg1 = LLVMGetParam(func, 0);
  171. LLVMBuilderRef builder = gallivm->builder;
  172. LLVMBasicBlockRef block = LLVMAppendBasicBlockInContext(context, func, "entry");
  173. LLVMValueRef index0 = LLVMConstInt(i32t, 0, 0);
  174. LLVMValueRef ret;
  175. struct lp_build_context bld;
  176. lp_build_context_init(&bld, gallivm, lp_type_float_vec(32));
  177. LLVMSetFunctionCallConv(func, LLVMCCallConv);
  178. LLVMPositionBuilderAtEnd(builder, block);
  179. /* scalar to vector */
  180. arg1 = LLVMBuildInsertElement(builder, LLVMGetUndef(vf32t), arg1, index0, "");
  181. ret = test->builder(&bld, arg1);
  182. /* vector to scalar */
  183. ret = LLVMBuildExtractElement(builder, ret, index0, "");
  184. LLVMBuildRet(builder, ret);
  185. return func;
  186. }
  187. /*
  188. * Test one LLVM unary arithmetic builder function.
  189. */
  190. static boolean
  191. test_unary(struct gallivm_state *gallivm, unsigned verbose, FILE *fp, const struct unary_test_t *test)
  192. {
  193. LLVMModuleRef module = gallivm->module;
  194. LLVMValueRef test_func;
  195. LLVMExecutionEngineRef engine = gallivm->engine;
  196. LLVMContextRef context = gallivm->context;
  197. char *error = NULL;
  198. unary_func_t test_func_jit;
  199. boolean success = TRUE;
  200. int i;
  201. test_func = build_unary_test_func(gallivm, module, context, test);
  202. if (LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
  203. printf("LLVMVerifyModule: %s\n", error);
  204. LLVMDumpModule(module);
  205. abort();
  206. }
  207. LLVMDisposeMessage(error);
  208. test_func_jit = (unary_func_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_func));
  209. for (i = 0; i < test->num_values; ++i) {
  210. float value = test->values[i];
  211. float ref = test->ref(value);
  212. float src = test_func_jit(value);
  213. double error = fabs(src - ref);
  214. double precision = error ? -log2(error/fabs(ref)) : FLT_MANT_DIG;
  215. bool pass = precision >= test->precision;
  216. if (isnan(ref)) {
  217. continue;
  218. }
  219. if (!pass || verbose) {
  220. printf("%s(%.9g): ref = %.9g, src = %.9g, precision = %f bits, %s\n",
  221. test->name, value, ref, src, precision,
  222. pass ? "PASS" : "FAIL");
  223. }
  224. if (!pass) {
  225. success = FALSE;
  226. }
  227. }
  228. LLVMFreeMachineCodeForFunction(engine, test_func);
  229. return success;
  230. }
  231. boolean
  232. test_all(struct gallivm_state *gallivm, unsigned verbose, FILE *fp)
  233. {
  234. boolean success = TRUE;
  235. int i;
  236. for (i = 0; i < Elements(unary_tests); ++i) {
  237. if (!test_unary(gallivm, verbose, fp, &unary_tests[i])) {
  238. success = FALSE;
  239. }
  240. }
  241. return success;
  242. }
  243. boolean
  244. test_some(struct gallivm_state *gallivm, unsigned verbose, FILE *fp,
  245. unsigned long n)
  246. {
  247. /*
  248. * Not randomly generated test cases, so test all.
  249. */
  250. return test_all(gallivm, verbose, fp);
  251. }
  252. boolean
  253. test_single(struct gallivm_state *gallivm, unsigned verbose, FILE *fp)
  254. {
  255. return TRUE;
  256. }