From ae7fb01363d742595c106845b509bb435247a5a4 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 16 Jul 2004 01:16:53 +0000 Subject: [PATCH] gst/gstvalue.c: use ints and return ints, fractions only use ints, too, so this avoids accidently casting multiplicat... Original commit message from CVS: * gst/gstvalue.c: (gst_greatest_common_divisor): use ints and return ints, fractions only use ints, too, so this avoids accidently casting multiplications to unsigned (gst_value_lcopy_fraction): it's ints, not uint32 (gst_value_set_fraction): disallow minint, multiplying and negation are broken with it (gst_value_fraction_multiply): fix to make large numbers work and get rid of the assumption that the multiplication of two ints fits an int64 - dunno if that's true for all systems * testsuite/caps/Makefile.am: * testsuite/caps/fraction-multiply-and-zero.c: (check_multiplication), (check_equal), (zero_test), (main): add tests for all the stuff above * testsuite/caps/value_compare.c: (test1): fix comment * tests/.cvsignore: * testsuite/caps/.cvsignore: * testsuite/debug/.cvsignore: * testsuite/dlopen/.cvsignore: * testsuite/states/.cvsignore: get up to date --- ChangeLog | 24 ++++ gst/gstvalue.c | 42 +++--- tests/.gitignore | 1 + tests/old/testsuite/caps/.gitignore | 6 +- tests/old/testsuite/caps/Makefile.am | 1 + .../caps/fraction-multiply-and-zero.c | 131 ++++++++++++++++++ tests/old/testsuite/caps/value_compare.c | 2 +- tests/old/testsuite/debug/.gitignore | 1 + tests/old/testsuite/dlopen/.gitignore | 1 + tests/old/testsuite/states/.gitignore | 2 + testsuite/caps/.gitignore | 6 +- testsuite/caps/Makefile.am | 1 + testsuite/caps/fraction-multiply-and-zero.c | 131 ++++++++++++++++++ testsuite/caps/value_compare.c | 2 +- testsuite/debug/.gitignore | 1 + testsuite/dlopen/.gitignore | 1 + testsuite/states/.gitignore | 2 + 17 files changed, 328 insertions(+), 27 deletions(-) create mode 100644 tests/old/testsuite/caps/fraction-multiply-and-zero.c create mode 100644 tests/old/testsuite/dlopen/.gitignore create mode 100644 testsuite/caps/fraction-multiply-and-zero.c create mode 100644 testsuite/dlopen/.gitignore diff --git a/ChangeLog b/ChangeLog index ee4c163d2a..24c38dd59f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2004-07-16 Benjamin Otte + + * gst/gstvalue.c: (gst_greatest_common_divisor): + use ints and return ints, fractions only use ints, too, so this + avoids accidently casting multiplications to unsigned + (gst_value_lcopy_fraction): it's ints, not uint32 + (gst_value_set_fraction): disallow minint, multiplying and negation + are broken with it + (gst_value_fraction_multiply): fix to make large numbers work and get + rid of the assumption that the multiplication of two ints fits an + int64 - dunno if that's true for all systems + * testsuite/caps/Makefile.am: + * testsuite/caps/fraction-multiply-and-zero.c: + (check_multiplication), (check_equal), (zero_test), (main): + add tests for all the stuff above + * testsuite/caps/value_compare.c: (test1): + fix comment + * tests/.cvsignore: + * testsuite/caps/.cvsignore: + * testsuite/debug/.cvsignore: + * testsuite/dlopen/.cvsignore: + * testsuite/states/.cvsignore: + get up to date + 2004-07-16 Zaheer Abbas Merali * docs/manual/bins-api.xml: diff --git a/gst/gstvalue.c b/gst/gstvalue.c index 1ff920da21..b87f4fc412 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -2298,8 +2298,8 @@ gst_type_is_fixed (GType type) /* Finds the greatest common divisor. * Returns 1 if none other found. * This is Euclid's algorithm. */ -static guint -gst_greatest_common_divisor (gint64 a, gint64 b) +static gint +gst_greatest_common_divisor (gint a, gint b) { while (b != 0) { int temp = a; @@ -2308,9 +2308,7 @@ gst_greatest_common_divisor (gint64 a, gint64 b) b = temp % b; } - g_return_val_if_fail (a < G_MAXINT, 1); - g_return_val_if_fail (a > G_MININT, 1); - return ABS ((gint) a); + return ABS (a); } static void @@ -2341,8 +2339,8 @@ static gchar * gst_value_lcopy_fraction (const GValue * value, guint n_collect_values, GTypeCValue * collect_values, guint collect_flags) { - guint32 *numerator = collect_values[0].v_pointer; - guint32 *denominator = collect_values[1].v_pointer; + gint *numerator = collect_values[0].v_pointer; + gint *denominator = collect_values[1].v_pointer; if (!numerator) return g_strdup_printf ("numerator for `%s' passed as NULL", @@ -2370,9 +2368,12 @@ gst_value_lcopy_fraction (const GValue * value, guint n_collect_values, void gst_value_set_fraction (GValue * value, gint numerator, gint denominator) { + gint gcd = 0; + g_return_if_fail (GST_VALUE_HOLDS_FRACTION (value)); g_return_if_fail (denominator != 0); - gint gcd = 0; + g_return_if_fail (denominator >= -G_MAXINT); + g_return_if_fail (numerator >= -G_MAXINT); /* normalize sign */ if (denominator < 0) { @@ -2437,10 +2438,7 @@ gboolean gst_value_fraction_multiply (GValue * product, const GValue * factor1, const GValue * factor2) { - gint64 n, d; - guint gcd; - - gint n1, n2, d1, d2; + gint gcd, n1, n2, d1, d2; g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE); g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE); @@ -2450,19 +2448,17 @@ gst_value_fraction_multiply (GValue * product, const GValue * factor1, d1 = factor1->data[1].v_int; d2 = factor2->data[1].v_int; - n = n1 * n2; - d = d1 * d2; + gcd = gst_greatest_common_divisor (n1, d2); + n1 /= gcd; + d2 /= gcd; + gcd = gst_greatest_common_divisor (n2, d1); + n2 /= gcd; + d1 /= gcd; - gcd = gst_greatest_common_divisor (n, d); - n /= gcd; - d /= gcd; + g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (n2), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); - g_return_val_if_fail (n < G_MAXINT, FALSE); - g_return_val_if_fail (n > G_MININT, FALSE); - g_return_val_if_fail (d < G_MAXINT, FALSE); - g_return_val_if_fail (d > G_MININT, FALSE); - - gst_value_set_fraction (product, n, d); + gst_value_set_fraction (product, n1 * n2, d1 * d2); return TRUE; } diff --git a/tests/.gitignore b/tests/.gitignore index 5429947afc..97d1b87cba 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -38,6 +38,7 @@ faketest events lat mass_elements +spidey_bench *.bb *.bbg *.da diff --git a/tests/old/testsuite/caps/.gitignore b/tests/old/testsuite/caps/.gitignore index 0e183c92d0..618ade7615 100644 --- a/tests/old/testsuite/caps/.gitignore +++ b/tests/old/testsuite/caps/.gitignore @@ -13,12 +13,16 @@ app_fixate audioscale caps compatibility -erathostenes +deserialize +eratosthenes filtercaps fixed +fraction-multiply-and-zero intersect2 intersection normalisation +random +renegotiate union simplify sets diff --git a/tests/old/testsuite/caps/Makefile.am b/tests/old/testsuite/caps/Makefile.am index f9bf989787..637e8cbc5a 100644 --- a/tests/old/testsuite/caps/Makefile.am +++ b/tests/old/testsuite/caps/Makefile.am @@ -10,6 +10,7 @@ tests_pass = \ union \ string-conversions \ fixed \ + fraction-multiply-and-zero \ intersect2 \ caps \ value_compare \ diff --git a/tests/old/testsuite/caps/fraction-multiply-and-zero.c b/tests/old/testsuite/caps/fraction-multiply-and-zero.c new file mode 100644 index 0000000000..50c0a53e75 --- /dev/null +++ b/tests/old/testsuite/caps/fraction-multiply-and-zero.c @@ -0,0 +1,131 @@ +/* GStreamer + * + * fraction.c: test for all GstFraction operations + * + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static void +check_multiplication (int num1, int den1, int num2, int den2, int num_result, + int den_result) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue value3 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + g_value_init (&value3, GST_TYPE_FRACTION); + + gst_value_set_fraction (&value1, num1, den1); + gst_value_set_fraction (&value2, num2, den2); + g_print ("%d/%d * %d/%d = ", num1, den1, num2, den2); + gst_value_fraction_multiply (&value3, &value1, &value2); + g_print ("%d/%d (should be %d/%d)\n", + gst_value_get_fraction_numerator (&value3), + gst_value_get_fraction_denominator (&value3), num_result, den_result); + g_assert (gst_value_get_fraction_numerator (&value3) == num_result); + g_assert (gst_value_get_fraction_denominator (&value3) == den_result); + + g_value_unset (&value1); + g_value_unset (&value2); + g_value_unset (&value3); +} + +static void +check_equal (int num1, int den1, int num2, int den2) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + + gst_value_set_fraction (&value1, num1, den1); + gst_value_set_fraction (&value2, num2, den2); + g_print ("%d/%d == %d/%d ? ", num1, den1, num2, den2); + g_assert (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL); + g_print ("yes\n"); + + g_value_unset (&value1); + g_value_unset (&value2); +} + +static void +zero_test (void) +{ + GValue value1 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + + /* fractions are initialized at 0 */ + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + + /* every zero value is set to 0/1 */ + gst_value_set_fraction (&value1, 0, 235); + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + gst_value_set_fraction (&value1, 0, -G_MAXINT); + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + + g_value_unset (&value1); +} + +int +main (int argc, char *argv[]) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue value3 = { 0 }; + + gst_init (&argc, &argv); + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + g_value_init (&value3, GST_TYPE_FRACTION); + + /*** zeroes ***/ + + /* basic zero tests */ + zero_test (); + + /* check all zeroes are zeroes */ + check_equal (0, 1, 0, 12345); + check_equal (0, 1, 0, -1); + + /* check multiplying with zeroes results in zeroes */ + check_multiplication (0, 1, 17, 18, 0, 1); + check_multiplication (0, -13, -G_MAXINT, 2736, 0, 1); + + /*** large numbers ***/ + + /* check multiplying large numbers works */ + check_multiplication (G_MAXINT, 1, G_MAXINT - 1, G_MAXINT, G_MAXINT - 1, 1); + check_multiplication (-G_MAXINT, 1, -G_MAXINT + 1, -G_MAXINT, -G_MAXINT + 1, + 1); + check_multiplication (G_MAXINT / 28, 459, -28, -G_MAXINT / 459, + G_MAXINT / 28 * 28, G_MAXINT / 459 * 459); + check_multiplication (3117 * 13, -17, 3117 * 17, 13, -3117 * 3117, 1); + + return 0; +} diff --git a/tests/old/testsuite/caps/value_compare.c b/tests/old/testsuite/caps/value_compare.c index cdce4bd718..e6c54129e1 100644 --- a/tests/old/testsuite/caps/value_compare.c +++ b/tests/old/testsuite/caps/value_compare.c @@ -72,7 +72,7 @@ test1 (void) g_value_unset (&value1); g_value_unset (&value2); - /* comparing 10/100 with 20/2000 */ + /* comparing 10/100 with 200/2000 */ g_value_init (&value1, GST_TYPE_FRACTION); gst_value_set_fraction (&value1, 10, 100); g_value_init (&value2, GST_TYPE_FRACTION); diff --git a/tests/old/testsuite/debug/.gitignore b/tests/old/testsuite/debug/.gitignore index 3908503d5f..592d5994d7 100644 --- a/tests/old/testsuite/debug/.gitignore +++ b/tests/old/testsuite/debug/.gitignore @@ -1,4 +1,5 @@ category commandline +global output printf_extension diff --git a/tests/old/testsuite/dlopen/.gitignore b/tests/old/testsuite/dlopen/.gitignore new file mode 100644 index 0000000000..3f9346b8de --- /dev/null +++ b/tests/old/testsuite/dlopen/.gitignore @@ -0,0 +1 @@ +dlopen_gst diff --git a/tests/old/testsuite/states/.gitignore b/tests/old/testsuite/states/.gitignore index 70b8e22885..031265d738 100644 --- a/tests/old/testsuite/states/.gitignore +++ b/tests/old/testsuite/states/.gitignore @@ -5,4 +5,6 @@ Makefile.in *.la .deps .libs + locked +parent diff --git a/testsuite/caps/.gitignore b/testsuite/caps/.gitignore index 0e183c92d0..618ade7615 100644 --- a/testsuite/caps/.gitignore +++ b/testsuite/caps/.gitignore @@ -13,12 +13,16 @@ app_fixate audioscale caps compatibility -erathostenes +deserialize +eratosthenes filtercaps fixed +fraction-multiply-and-zero intersect2 intersection normalisation +random +renegotiate union simplify sets diff --git a/testsuite/caps/Makefile.am b/testsuite/caps/Makefile.am index f9bf989787..637e8cbc5a 100644 --- a/testsuite/caps/Makefile.am +++ b/testsuite/caps/Makefile.am @@ -10,6 +10,7 @@ tests_pass = \ union \ string-conversions \ fixed \ + fraction-multiply-and-zero \ intersect2 \ caps \ value_compare \ diff --git a/testsuite/caps/fraction-multiply-and-zero.c b/testsuite/caps/fraction-multiply-and-zero.c new file mode 100644 index 0000000000..50c0a53e75 --- /dev/null +++ b/testsuite/caps/fraction-multiply-and-zero.c @@ -0,0 +1,131 @@ +/* GStreamer + * + * fraction.c: test for all GstFraction operations + * + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +static void +check_multiplication (int num1, int den1, int num2, int den2, int num_result, + int den_result) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue value3 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + g_value_init (&value3, GST_TYPE_FRACTION); + + gst_value_set_fraction (&value1, num1, den1); + gst_value_set_fraction (&value2, num2, den2); + g_print ("%d/%d * %d/%d = ", num1, den1, num2, den2); + gst_value_fraction_multiply (&value3, &value1, &value2); + g_print ("%d/%d (should be %d/%d)\n", + gst_value_get_fraction_numerator (&value3), + gst_value_get_fraction_denominator (&value3), num_result, den_result); + g_assert (gst_value_get_fraction_numerator (&value3) == num_result); + g_assert (gst_value_get_fraction_denominator (&value3) == den_result); + + g_value_unset (&value1); + g_value_unset (&value2); + g_value_unset (&value3); +} + +static void +check_equal (int num1, int den1, int num2, int den2) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + + gst_value_set_fraction (&value1, num1, den1); + gst_value_set_fraction (&value2, num2, den2); + g_print ("%d/%d == %d/%d ? ", num1, den1, num2, den2); + g_assert (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL); + g_print ("yes\n"); + + g_value_unset (&value1); + g_value_unset (&value2); +} + +static void +zero_test (void) +{ + GValue value1 = { 0 }; + + g_value_init (&value1, GST_TYPE_FRACTION); + + /* fractions are initialized at 0 */ + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + + /* every zero value is set to 0/1 */ + gst_value_set_fraction (&value1, 0, 235); + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + gst_value_set_fraction (&value1, 0, -G_MAXINT); + g_assert (gst_value_get_fraction_numerator (&value1) == 0); + g_assert (gst_value_get_fraction_denominator (&value1) == 1); + + g_value_unset (&value1); +} + +int +main (int argc, char *argv[]) +{ + GValue value1 = { 0 }; + GValue value2 = { 0 }; + GValue value3 = { 0 }; + + gst_init (&argc, &argv); + + g_value_init (&value1, GST_TYPE_FRACTION); + g_value_init (&value2, GST_TYPE_FRACTION); + g_value_init (&value3, GST_TYPE_FRACTION); + + /*** zeroes ***/ + + /* basic zero tests */ + zero_test (); + + /* check all zeroes are zeroes */ + check_equal (0, 1, 0, 12345); + check_equal (0, 1, 0, -1); + + /* check multiplying with zeroes results in zeroes */ + check_multiplication (0, 1, 17, 18, 0, 1); + check_multiplication (0, -13, -G_MAXINT, 2736, 0, 1); + + /*** large numbers ***/ + + /* check multiplying large numbers works */ + check_multiplication (G_MAXINT, 1, G_MAXINT - 1, G_MAXINT, G_MAXINT - 1, 1); + check_multiplication (-G_MAXINT, 1, -G_MAXINT + 1, -G_MAXINT, -G_MAXINT + 1, + 1); + check_multiplication (G_MAXINT / 28, 459, -28, -G_MAXINT / 459, + G_MAXINT / 28 * 28, G_MAXINT / 459 * 459); + check_multiplication (3117 * 13, -17, 3117 * 17, 13, -3117 * 3117, 1); + + return 0; +} diff --git a/testsuite/caps/value_compare.c b/testsuite/caps/value_compare.c index cdce4bd718..e6c54129e1 100644 --- a/testsuite/caps/value_compare.c +++ b/testsuite/caps/value_compare.c @@ -72,7 +72,7 @@ test1 (void) g_value_unset (&value1); g_value_unset (&value2); - /* comparing 10/100 with 20/2000 */ + /* comparing 10/100 with 200/2000 */ g_value_init (&value1, GST_TYPE_FRACTION); gst_value_set_fraction (&value1, 10, 100); g_value_init (&value2, GST_TYPE_FRACTION); diff --git a/testsuite/debug/.gitignore b/testsuite/debug/.gitignore index 3908503d5f..592d5994d7 100644 --- a/testsuite/debug/.gitignore +++ b/testsuite/debug/.gitignore @@ -1,4 +1,5 @@ category commandline +global output printf_extension diff --git a/testsuite/dlopen/.gitignore b/testsuite/dlopen/.gitignore new file mode 100644 index 0000000000..3f9346b8de --- /dev/null +++ b/testsuite/dlopen/.gitignore @@ -0,0 +1 @@ +dlopen_gst diff --git a/testsuite/states/.gitignore b/testsuite/states/.gitignore index 70b8e22885..031265d738 100644 --- a/testsuite/states/.gitignore +++ b/testsuite/states/.gitignore @@ -5,4 +5,6 @@ Makefile.in *.la .deps .libs + locked +parent