diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-08-14 11:12:50 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2009-08-14 11:12:50 +0200 |
commit | 2919e5add82966150586684b3efb43509d971a80 (patch) | |
tree | 6841a9d3e9c552ab86b7f05eb29042d16360e2e8 | |
parent | 76338950f9d077f67f3fe4329cf790eafe18e836 (diff) |
gstutils: Add special random unit test for 64 scaling functions
This tests 100000 random multiplications/divisions of all scaling
function variants and compares the result with the result that is
generated by GMP on the same input.
For this check for GSL and GMP during configure but only use
it for this single unit test.
Testing functions were provided by Kipp Cannon <kcannon@ligo.caltech.edu>
-rw-r--r-- | configure.ac | 19 | ||||
-rw-r--r-- | tests/check/Makefile.am | 2 | ||||
-rw-r--r-- | tests/check/gst/gstutils.c | 165 |
3 files changed, 186 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index ca0fcb9029..c079924fce 100644 --- a/configure.ac +++ b/configure.ac @@ -323,6 +323,25 @@ if test "x$HAVE_WINSOCK2_H" = "xyes"; then AC_SUBST(WIN32_LIBS) fi +dnl check for GMP/GSL, used by the gst_util_uint64_scale unit test only +AG_GST_CHECK_LIBHEADER(GMP, gmp, + __gmpz_init_set_d, , + gmp.h, + GMP_LIBS="-lgmp" + AC_SUBST(GMP_LIBS) + AC_DEFINE(HAVE_GMP, [1],[Have GMP library])) +AG_GST_CHECK_LIBHEADER(GSL, gsl, + gsl_rng_uniform_int, -lgslcblas, + gsl/gsl_rng.h, + GSL_LIBS="-lgsl -lgslcblas" + AC_SUBST(GSL_LIBS) + AC_DEFINE(HAVE_GSL, [1],[Have GSL library])) + +AC_CHECK_LIB(rt, clock_gettime, [ + AC_DEFINE(HAVE_CLOCK_GETTIME, 1) + LIBS="$LIBS -lrt" +]) + dnl *** checks for types/defines *** dnl *** checks for structures *** diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 4c32289f58..3437792dbf 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -143,6 +143,8 @@ LDADD = $(top_builddir)/libs/gst/check/libgstcheck-@GST_MAJORMINOR@.la \ $(GST_OBJ_LIBS) \ $(CHECK_LIBS) +gst_gstutils_LDADD = $(LDADD) $(GSL_LIBS) $(GMP_LIBS) + libs_gdp_SOURCES = \ libs/gdp.c libs_gdp_CFLAGS = $(AM_CFLAGS) diff --git a/tests/check/gst/gstutils.c b/tests/check/gst/gstutils.c index ecf1e74fc0..e7a29df8e2 100644 --- a/tests/check/gst/gstutils.c +++ b/tests/check/gst/gstutils.c @@ -20,6 +20,10 @@ * Boston, MA 02111-1307, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gst/check/gstcheck.h> #define SPECIAL_POINTER(x) ((void*)(19283847+(x))) @@ -738,6 +742,160 @@ GST_START_TEST (test_binary_search) GST_END_TEST; +#ifdef HAVE_GSL +#ifdef HAVE_GMP + +#include <gsl/gsl_rng.h> +#include <gmp.h> + +static guint64 +randguint64 (gsl_rng * rng, guint64 n) +{ + union + { + guint64 x; + struct + { + guint16 a, b, c, d; + } parts; + } x; + x.parts.a = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.b = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.c = gsl_rng_uniform_int (rng, 1 << 16); + x.parts.d = gsl_rng_uniform_int (rng, 1 << 16); + return x.x % n; +} + + +enum round_t +{ + ROUND_TONEAREST = 0, + ROUND_UP, + ROUND_DOWN +}; + +static guint64 +gmp_scale (guint64 x, guint64 a, guint64 b, enum round_t mode) +{ + mpz_t mp1, mp2; + if (!b) + /* overflow */ + return G_MAXUINT64; + mpz_init_set_ui (mp1, x); + mpz_init (mp2); + mpz_mul_ui (mp2, mp1, a); + switch (mode) { + case ROUND_TONEAREST: + mpz_add_ui (mp1, mp2, b / 2); + mpz_set (mp2, mp1); + break; + case ROUND_UP: + mpz_add_ui (mp1, mp2, b - 1); + mpz_set (mp2, mp1); + break; + case ROUND_DOWN: + break; + } + mpz_tdiv_q_ui (mp1, mp2, b); + x = mpz_get_ui (mp1); + mpz_clear (mp1); + mpz_clear (mp2); + return x; +} + +static void +_gmp_test_scale (gsl_rng * rng) +{ + guint64 bygst, bygmp; + guint64 a = randguint64 (rng, gsl_rng_uniform_int (rng, + 2) ? G_MAXUINT64 : G_MAXUINT32); + guint64 b = randguint64 (rng, gsl_rng_uniform_int (rng, 2) ? G_MAXUINT64 - 1 : G_MAXUINT32 - 1) + 1; /* 0 not allowed */ + guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN)); + enum round_t mode = gsl_rng_uniform_int (rng, 3); + const char *func; + + bygmp = gmp_scale (val, a, b, mode); + switch (mode) { + case ROUND_TONEAREST: + bygst = gst_util_uint64_scale_round (val, a, b); + func = "gst_util_uint64_scale_round"; + break; + case ROUND_UP: + bygst = gst_util_uint64_scale_ceil (val, a, b); + func = "gst_util_uint64_scale_ceil"; + break; + case ROUND_DOWN: + bygst = gst_util_uint64_scale (val, a, b); + func = "gst_util_uint64_scale"; + break; + } + fail_unless (bygst == bygmp, + "error: %s(): %" G_GUINT64_FORMAT " * %" G_GUINT64_FORMAT " / %" + G_GUINT64_FORMAT " = %" G_GUINT64_FORMAT ", correct = %" G_GUINT64_FORMAT + "\n", func, val, a, b, bygst, bygmp); +} + +static void +_gmp_test_scale_int (gsl_rng * rng) +{ + guint64 bygst, bygmp; + gint32 a = randguint64 (rng, G_MAXINT32); + gint32 b = randguint64 (rng, G_MAXINT32 - 1) + 1; /* 0 not allowed */ + guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN)); + enum round_t mode = gsl_rng_uniform_int (rng, 3); + const char *func; + + bygmp = gmp_scale (val, a, b, mode); + switch (mode) { + case ROUND_TONEAREST: + bygst = gst_util_uint64_scale_int_round (val, a, b); + func = "gst_util_uint64_scale_int_round"; + break; + case ROUND_UP: + bygst = gst_util_uint64_scale_int_ceil (val, a, b); + func = "gst_util_uint64_scale_int_ceil"; + break; + case ROUND_DOWN: + bygst = gst_util_uint64_scale_int (val, a, b); + func = "gst_util_uint64_scale_int"; + break; + } + fail_unless (bygst == bygmp, + "error: %s(): %" G_GUINT64_FORMAT " * %d / %d = %" G_GUINT64_FORMAT + ", correct = %" G_GUINT64_FORMAT "\n", func, val, a, b, bygst, bygmp); +} + +#define GMP_TEST_RUNS 100000 + +GST_START_TEST (test_math_scale_gmp) +{ + gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937); + gint n; + + for (n = 0; n < GMP_TEST_RUNS; n++) + _gmp_test_scale (rng); + + gsl_rng_free (rng); +} + +GST_END_TEST; + +GST_START_TEST (test_math_scale_gmp_int) +{ + gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937); + gint n; + + for (n = 0; n < GMP_TEST_RUNS; n++) + _gmp_test_scale_int (rng); + + gsl_rng_free (rng); +} + +GST_END_TEST; + +#endif +#endif + static Suite * gst_utils_suite (void) { @@ -752,6 +910,13 @@ gst_utils_suite (void) tcase_add_test (tc_chain, test_math_scale_ceil); tcase_add_test (tc_chain, test_math_scale_uint64); tcase_add_test (tc_chain, test_math_scale_random); +#ifdef HAVE_GSL +#ifdef HAVE_GMP + tcase_add_test (tc_chain, test_math_scale_gmp); + tcase_add_test (tc_chain, test_math_scale_gmp_int); +#endif +#endif + tcase_add_test (tc_chain, test_guint64_to_gdouble); tcase_add_test (tc_chain, test_gdouble_to_guint64); #ifndef GST_DISABLE_PARSE |