diff -r e4d67989cc36 -r 47c74d1534e1 genericopenlibs/liboil/src/liboiltest.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/genericopenlibs/liboil/src/liboiltest.c Fri Apr 16 16:46:38 2010 +0300 @@ -0,0 +1,778 @@ +/* + * LIBOIL - Library of Optimized Inner Loops + * Copyright (c) 2003,2004 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +//Portions Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __SYMBIAN32__ +#ifdef __WINSCW__ +#pragma warn_unusedarg off +#endif//__WINSCW__ +#endif//__SYMBIAN32__ + +#define MAX_PARAMS 20 + +/** + * SECTION:liboiltest + * @title:OilTest + * @short_description: Test and profile function implementations. + * + */ +static void oil_test_init_params (OilTest *test); +static void fill_array (void *ptr, OilType type, int pre_n, int stride, + int post_n); +static double check_array (void *data, void *ref, OilType type, int pre_n, + int stride, int post_n); +static int check_holes (void *data, OilType type, int pre_n, + int stride, int post_n, int guard); + +/** + * oil_test_new: + * @klass: an OilFunctionClass + * + * Creates a new OilTest for the OilFunctionClass represented by @klass. + * + * Returns: the new OilTest + */ +#ifdef __SYMBIAN32__ +EXPORT_C +#endif +OilTest * +oil_test_new (OilFunctionClass *klass) +{ + OilTest *test; + OilPrototype *proto; + int i; + + if (klass == NULL) return NULL; + + proto = oil_prototype_from_string (klass->prototype); + if (proto == NULL) return NULL; + + test = malloc (sizeof (OilTest)); + memset (test, 0, sizeof (OilTest)); + + test->klass = klass; + test->proto = proto; + test->impl = klass->reference_impl; + test->tolerance = 0.0; + + for (i=0;in_params;i++){ + if (proto->params[i].parameter_type == OIL_ARG_UNKNOWN) { + return NULL; + } + if (oil_type_is_floating_point(proto->params[i].type)) { + test->tolerance = 0.001; + } + memcpy (&test->params[proto->params[i].parameter_type], &proto->params[i], + sizeof(OilParameter)); + } + for (i=0;iparams[i].src_data = NULL; + test->params[i].ref_data = NULL; + test->params[i].test_data = NULL; + test->params[i].test_header = OIL_TEST_HEADER; + test->params[i].test_footer = OIL_TEST_FOOTER; + } + + test->iterations = 10; + test->n = 100; + test->m = 100; + + return test; +} + +/** + * oil_test_free: + * @test: the OilTest + * + * Frees memory associated with @test. + */ + #ifdef __SYMBIAN32__ +EXPORT_C +#endif +void +oil_test_free (OilTest *test) +{ + int i; + + if (test->proto) { + oil_prototype_free (test->proto); + } + + for(i=0;iparams[i].src_data) { + free (test->params[i].src_data); + } + if (test->params[i].ref_data) { + free (test->params[i].ref_data); + } + if (test->params[i].test_data) { + free (test->params[i].test_data); + } + } + + free(test); +} + +/** + * oil_test_set_impl: + * @test: the OilTest + * @impl: an OilFunctionImpl to set + * + * Sets the current implementation of @test to @impl. + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_set_impl (OilTest *test, OilFunctionImpl *impl) +{ + test->impl = impl; +} + +/** + * oil_test_set_iterations: + * @test: the OilTest + * @iterations: the number of iterations + * + * Sets the number of iterations of @test to @iterations. + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_set_iterations (OilTest *test, int iterations) +{ + test->iterations = iterations; +} + +/** + * oil_test_set_test_header: + * @test: the OilTest + * @p: the OilParameter to change the header for + * @test_header: the number of bytes of guard header + * + * Sets the number of bytes of guard header for @p to @test_header. + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_set_test_header (OilTest *test, OilParameter *p, int test_header) +{ + p->test_header = test_header; +} + +/** + * oil_test_set_test_footer: + * @test: the OilTest + * @p: the OilParameter to change the footer for + * @test_footer: the number of bytes of guard footer + * + * Sets the number of bytes of guard footer for @p to @test_footer. + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_set_test_footer (OilTest *test, OilParameter *p, int test_footer) +{ + p->test_footer = test_footer; +} + +/** + * oil_test_init: + * @test: the OilTest + * + * Intializes @test. + * + * FIXME: needs work + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_init (OilTest *test) +{ + if (test->inited) { + return; + } + + oil_test_init_params(test); + + test->params[OIL_ARG_N].value = test->n; + + test->inited = 1; + + if (test->klass->test_func) { + test->klass->test_func (test); + } +} + +#ifdef __WINSCW__ +#pragma suppress_warnings on +#endif//__WINSCW__ +#ifdef __ARMCC__ +#pragma diag_remark 188 +#endif//__ARMCC__ + +static void +oil_test_check_function (void * priv) +{ + OilTest *test = priv; + int i; + int j; + unsigned long args[MAX_PARAMS]; + unsigned int pointer_mask; + + oil_test_init (test); + + OIL_LOG("calling function %s", test->impl->name); + + pointer_mask = 1; + for(i=0;iproto->n_params;i++){ + OilParameter *p; + j = test->proto->params[i].parameter_type; + p = &test->params[j]; + + pointer_mask <<= 1; + OIL_LOG(" %s: 0x%08lx (%ld)", oil_arg_type_name (j), p->value, p->value); + if (p->is_pointer) { + pointer_mask |= 1; + if (p->direction == 's') { + args[i] = (unsigned long)p->src_data + p->test_header; + } else if (p->direction == 'i') { + memcpy (p->test_data, p->src_data, p->size); + args[i] = (unsigned long)p->test_data + p->test_header; + } else if (p->direction == 'd') { + memset (p->test_data, p->guard, p->size); + args[i] = (unsigned long)p->test_data + p->test_header; + } else { + OIL_ERROR ("not reached"); + } + } else { + args[i] = p->value; + } + } +#ifdef __WINSCW__ +#pragma suppress_warnings off +#endif//__WINSCW__ + + oil_profile_init (&test->prof); + for(i=0;iiterations;i++){ + int k; + + for(k=0;kproto->n_params;k++){ + OilParameter *p; + j = test->proto->params[k].parameter_type; + p = &test->params[j]; + if (p->direction == 'i') { + memcpy (p->test_data, p->src_data, p->size); + } + } + _oil_test_marshal_function (test->impl->func, args, test->proto->n_params, + pointer_mask, &test->prof); + } + + oil_profile_get_ave_std (&test->prof, &test->profile_ave, + &test->profile_std); +} + +/** + * oil_test_check_ref: + * @test: the OilTest + * + * Runs the test specified by @test on the reference function of the + * class being tested. + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_check_ref (OilTest *test) +{ + int i; + + if (test->proto->n_params > MAX_PARAMS) { + OIL_ERROR ("function class %s has too many parameters", + test->klass->name); + return; + } + if (test->klass->reference_impl == NULL) { + OIL_ERROR ("function class %s has no reference implementation", + test->klass->name); + return; + } + + test->impl = test->klass->reference_impl; + + oil_test_check_function (test); + + for(i=0;iparams[i]; + + if (p->is_pointer) { + if (p->direction == 'i' || p->direction == 'd') { + memcpy (p->ref_data, p->test_data, p->size); + } + } + } + + test->tested_ref = 1; +} + +static int +check_guard (uint8_t *data, int n, int guard) +{ + int i; + for(i=0;iproto->n_params > MAX_PARAMS) { + OIL_ERROR ("function has too many parameters"); + return 0; + } + + if (!test->inited || !test->tested_ref) { + oil_test_check_ref(test); + } + + test->impl = impl; + ret = oil_fault_check_try (oil_test_check_function, test); + if (!ret) { + OIL_ERROR ("illegal instruction in %s", test->impl->name); + test->profile_ave = 0; + test->profile_std = 0; + + return 0; + } + + x = 0; + n = 0; + for(i=0;iparams[i]; + + if (p->is_pointer) { + if (p->direction == 'i' || p->direction == 'd') { + x += check_array (p->test_data + p->test_header, + p->ref_data + p->test_header, p->type, p->pre_n, p->stride, + p->post_n); + n += p->pre_n * p->post_n; + if (!check_guard (p->test_data, p->test_header, p->guard)) { + fail = 1; + OIL_ERROR("function %s wrote before area for parameter %s", + test->impl->name, p->parameter_name); + } + if (!check_guard ((uint8_t *)p->test_data + p->size - p->test_footer, + p->test_footer, p->guard)) { + fail = 1; + OIL_ERROR("function %s wrote after area for parameter %s", + test->impl->name, p->parameter_name); + } + if (!check_holes (p->test_data, p->type, p->pre_n, p->stride, + p->post_n, p->guard)) { + fail = 1; + OIL_ERROR("function %s wrote in interstitial area for parameter %s", + test->impl->name, p->parameter_name); + } + } + } + } + OIL_DEBUG("sum of absolute differences %g for %d values", x, n); + test->sum_abs_diff = x; + test->n_points = n; + + if (x > test->tolerance * n || fail) { + OIL_ERROR ("function %s in class %s failed check (%g > %g) || (outside=%d)", + test->impl->name, test->klass->name, x, test->tolerance * n, fail); + return 0; + } + + return 1; +} + +/** + * oil_test_cleanup + * @test: the OilTest + * + * Cleans up @test. + * + * FIXME: needs work + */ + #ifdef __SYMBIAN32__ + EXPORT_C +#endif +void +oil_test_cleanup (OilTest *test) +{ + OilParameter *params = test->params; + + /* src1 */ + if(params[OIL_ARG_SRC1].type) { + if (!params[OIL_ARG_SSTR1].type) { + params[OIL_ARG_SSTR1].value = oil_type_sizeof (params[OIL_ARG_SRC1].type); + } + } + + /* src2 */ + if(params[OIL_ARG_SRC2].type) { + if (!params[OIL_ARG_SSTR2].type) { + params[OIL_ARG_SSTR2].value = oil_type_sizeof (params[OIL_ARG_SRC2].type); + } + } + + /* src3 */ + if(params[OIL_ARG_SRC3].type) { + if (!params[OIL_ARG_SSTR3].type) { + params[OIL_ARG_SSTR3].value = oil_type_sizeof (params[OIL_ARG_SRC3].type); + } + } + + /* dest1 */ + if(params[OIL_ARG_DEST1].type) { + if (!params[OIL_ARG_DSTR1].type) { + params[OIL_ARG_DSTR1].value = oil_type_sizeof (params[OIL_ARG_DEST1].type); + } + } + + /* dest2 */ + if(params[OIL_ARG_DEST2].type) { + if (!params[OIL_ARG_DSTR2].type) { + params[OIL_ARG_DSTR2].value = oil_type_sizeof (params[OIL_ARG_DEST2].type); + } + } + + /* dest3 */ + if(params[OIL_ARG_DEST3].type) { + if (!params[OIL_ARG_DSTR3].type) { + params[OIL_ARG_DSTR3].value = oil_type_sizeof (params[OIL_ARG_DEST3].type); + } + } + +} + + +static void +init_parameter (OilTest *test, OilParameter *p, OilParameter *ps) +{ + if (!p->type) return; + + p->pre_n = p->prestride_length; + if (p->prestride_var == 1) { + p->pre_n += test->n; + } + if (p->prestride_var == 2) { + p->pre_n += test->m; + } + + if (ps->value) { + p->stride = ps->value; + } else { + p->stride = oil_type_sizeof (p->type) * p->pre_n; + ps->value = p->stride; + } + + p->post_n = p->poststride_length; + if (p->poststride_var == 1) { + p->post_n += test->n; + } + if (p->poststride_var == 2) { + p->post_n += test->m; + } + + p->size = p->stride * p->post_n + p->test_header + p->test_footer; + p->guard = oil_rand_u8(); + + if (p->direction == 'i' || p->direction == 's') { + if (p->src_data) free (p->src_data); + + OIL_DEBUG("allocating %d bytes for src_data for %s", p->size, p->parameter_name); + p->src_data = malloc (p->size); + memset (p->src_data, p->guard, p->size); + fill_array (p->src_data + p->test_header, p->type, p->pre_n, p->stride, p->post_n); + } + + if (p->direction == 'i' || p->direction == 'd') { + if (p->ref_data) free (p->ref_data); + p->ref_data = malloc (p->size); + memset (p->ref_data, p->guard, p->size); + OIL_DEBUG("allocating %d bytes for ref_data and test_data for %s", p->size, p->parameter_name); + + if (p->test_data) free (p->test_data); + p->test_data = malloc (p->size); + memset (p->test_data, p->guard, p->size); + } +} + +static void +oil_test_init_params (OilTest *test) +{ + init_parameter (test, &test->params[OIL_ARG_DEST1], + &test->params[OIL_ARG_DSTR1]); + init_parameter (test, &test->params[OIL_ARG_DEST2], + &test->params[OIL_ARG_DSTR2]); + init_parameter (test, &test->params[OIL_ARG_DEST3], + &test->params[OIL_ARG_DSTR3]); + + init_parameter (test, &test->params[OIL_ARG_SRC1], + &test->params[OIL_ARG_SSTR1]); + init_parameter (test, &test->params[OIL_ARG_SRC2], + &test->params[OIL_ARG_SSTR2]); + init_parameter (test, &test->params[OIL_ARG_SRC3], + &test->params[OIL_ARG_SSTR3]); + init_parameter (test, &test->params[OIL_ARG_SRC4], + &test->params[OIL_ARG_SSTR4]); + init_parameter (test, &test->params[OIL_ARG_SRC5], + &test->params[OIL_ARG_SSTR5]); + + init_parameter (test, &test->params[OIL_ARG_INPLACE1], + &test->params[OIL_ARG_ISTR1]); + init_parameter (test, &test->params[OIL_ARG_INPLACE2], + &test->params[OIL_ARG_ISTR2]); +} + +static void +fill_array (void *data, OilType type, int pre_n, int stride, int post_n) +{ + int i; + +#define FILL(type,func) do {\ + for(i=0;iparams[arg_type].src_data; + ptr += test->params[arg_type].test_header; + + return ptr; +} + +#ifdef __SYMBIAN32__ + EXPORT_C +#endif +int +oil_test_get_arg_pre_n (OilTest *test, OilArgType arg_type) +{ + return test->params[arg_type].pre_n; +} + +#ifdef __SYMBIAN32__ + EXPORT_C +#endif +int +oil_test_get_arg_post_n (OilTest *test, OilArgType arg_type) +{ + return test->params[arg_type].post_n; +} + +#ifdef __SYMBIAN32__ + EXPORT_C +#endif +int +oil_test_get_arg_stride (OilTest *test, OilArgType arg_type) +{ + return test->params[arg_type].stride; +} + +#ifdef __SYMBIAN32__ + EXPORT_C +#endif +int +oil_test_get_value (OilTest *test, OilArgType arg_type) +{ + return test->params[arg_type].value; +}