summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2009-08-14 11:12:50 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-08-14 11:12:50 +0200
commit2919e5add82966150586684b3efb43509d971a80 (patch)
tree6841a9d3e9c552ab86b7f05eb29042d16360e2e8
parent76338950f9d077f67f3fe4329cf790eafe18e836 (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.ac19
-rw-r--r--tests/check/Makefile.am2
-rw-r--r--tests/check/gst/gstutils.c165
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