[Gnucash-changes] add double-precision tests,
add tests of multiplication of random
Linas Vepstas
linas at cvs.gnucash.org
Sat Jun 26 02:12:09 EDT 2004
Log Message:
-----------
add double-precision tests,
add tests of multiplication of random numbers
Modified Files:
--------------
gnucash/src/engine/test:
test-numeric.c
Revision Data
-------------
Index: test-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/test/test-numeric.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -Lsrc/engine/test/test-numeric.c -Lsrc/engine/test/test-numeric.c -u -r1.8 -r1.9
--- src/engine/test/test-numeric.c
+++ src/engine/test/test-numeric.c
@@ -15,18 +15,20 @@
#include "test-engine-stuff.h"
#include "gnc-numeric.h"
-#define NREPS 3000
-
+#define NREPS 1000
static char *
-gnc_numeric_print(gnc_numeric in) {
+gnc_numeric_print(gnc_numeric in)
+{
char * retval;
- if(gnc_numeric_check(in)) {
+ if(gnc_numeric_check(in))
+ {
retval = g_strdup_printf("<ERROR> [%lld / %lld]",
(long long int) in.num,
(long long int) in.denom);
}
- else {
+ else
+ {
retval = g_strdup_printf("[%lld / %lld]",
(long long int) in.num,
(long long int) in.denom);
@@ -34,6 +36,8 @@
return retval;
}
+/* ======================================================= */
+
static void
check_unary_op (gboolean (*eqtest) (gnc_numeric, gnc_numeric),
gnc_numeric expected,
@@ -54,6 +58,8 @@
g_free (str);
}
+/* ======================================================= */
+
static void
check_binary_op (gnc_numeric expected,
gnc_numeric actual,
@@ -76,64 +82,7 @@
g_free (str);
}
-#ifdef XXX_GNC_NUMERIC_TEST
-int
-main(int argc, char ** argv) {
- gnc_numeric a = gnc_numeric_create(1, 3);
- gnc_numeric b = gnc_numeric_create(1, 4);
- gnc_numeric d = gnc_numeric_create(1, 2);
-
- gnc_numeric err;
- int i;
- gint64 v;
-
- printf("7/16 as float: %e\n",
- gnc_numeric_to_double(gnc_numeric_create(7, 16)));
-
- printf("add LCM: %s + %s = %s\n",
- gnc_numeric_print(b), gnc_numeric_print(d),
- gnc_numeric_print(gnc_numeric_add(b, d, GNC_DENOM_AUTO,
- GNC_DENOM_LCD)));
-
- printf("float to 6 sigfigs: %s\n",
- gnc_numeric_print(double_to_gnc_numeric(1.1234567890123,
- GNC_DENOM_AUTO,
- GNC_DENOM_SIGFIGS(6) |
- GNC_RND_ROUND)));
- printf("float to 6 sigfigs: %s\n",
- gnc_numeric_print(double_to_gnc_numeric(.011234567890123,
- GNC_DENOM_AUTO,
- GNC_DENOM_SIGFIGS(6) |
- GNC_RND_ROUND)));
- printf("float to 6 sigfigs: %s\n",
- gnc_numeric_print(double_to_gnc_numeric(1123.4567890123,
- GNC_DENOM_AUTO,
- GNC_DENOM_SIGFIGS(6) |
- GNC_RND_ROUND)));
- printf("float to 6 sigfigs: %s\n",
- gnc_numeric_print(double_to_gnc_numeric(1.1234567890123e-5,
- GNC_DENOM_AUTO,
- GNC_DENOM_SIGFIGS(6) |
- GNC_RND_ROUND)));
- printf("add to 4 sigfigs: %s + %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_add(a, b,
- GNC_DENOM_AUTO,
- GNC_DENOM_SIGFIGS(4) |
- GNC_RND_ROUND)));
-
-
- v = 1000000;
- a = gnc_numeric_create(1*v, v);
- b = gnc_numeric_create(10000000*v, v);
- printf("multiply (LCD): %s * %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_DENOM_LCD)));
-
-
- return 0;
-}
-#endif
+/* ======================================================= */
static gboolean
gnc_numeric_unequal (gnc_numeric a, gnc_numeric b)
@@ -141,6 +90,8 @@
return (0 == gnc_numeric_equal (a,b));
}
+/* ======================================================= */
+
/* Make sure that the equivalence operator we use for
* later tests actually works */
static void
@@ -156,6 +107,7 @@
do_test (0 == gnc_numeric_eq(a, c), "expected inequivalence");
}
+/* ======================================================= */
static void
check_reduce (void)
@@ -193,6 +145,8 @@
val, "expected %s = %s = reduce(%s)");
}
+/* ======================================================= */
+
static void
check_equality_operator (void)
{
@@ -275,6 +229,8 @@
}
}
+/* ======================================================= */
+
static void
check_rounding (void)
{
@@ -336,12 +292,57 @@
val, "expected %s = %s = (%s as 100th's round)");
}
+/* ======================================================= */
+
+static void
+check_double (void)
+{
+ gnc_numeric val = gnc_numeric_create (0,1);
+
+ check_unary_op (gnc_numeric_eq,
+ gnc_numeric_create (112346,100000),
+ double_to_gnc_numeric(1.1234567890123,
+ GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(6) |
+ GNC_RND_ROUND),
+ val, "expected %s = %s double 6 figs");
+
+ check_unary_op (gnc_numeric_eq,
+ gnc_numeric_create (112346,10000000),
+ double_to_gnc_numeric(0.011234567890123,
+ GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(6) |
+ GNC_RND_ROUND),
+ val, "expected %s = %s double 6 figs");
+
+ check_unary_op (gnc_numeric_eq,
+ gnc_numeric_create (112346,100),
+ double_to_gnc_numeric(1123.4567890123,
+ GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(6) |
+ GNC_RND_ROUND),
+ val, "expected %s = %s double 6 figs");
+ check_unary_op (gnc_numeric_eq,
+ gnc_numeric_create (112346,10000000000LL),
+ double_to_gnc_numeric(1.1234567890123e-5,
+ GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(6) |
+ GNC_RND_ROUND),
+ val, "expected %s = %s double 6 figs");
+
+ double flo = gnc_numeric_to_double(gnc_numeric_create(7, 16));
+ do_test ((0.4375 == flo), "float pt conversion");
+}
+
+/* ======================================================= */
+
static void
check_add_subtract (void)
{
- gnc_numeric a = gnc_numeric_create(1, 3);
+ gnc_numeric a = gnc_numeric_create(2, 6);
gnc_numeric b = gnc_numeric_create(1, 4);
+ /* Well, actually 14/24 would be acceptable/better in this case */
check_binary_op (gnc_numeric_create(7,12),
gnc_numeric_add(a, b, GNC_DENOM_AUTO, GNC_DENOM_EXACT),
a, b, "expected %s got %s = %s + %s for add exact");
@@ -350,17 +351,34 @@
gnc_numeric_add(a, b, 100, GNC_RND_ROUND),
a, b, "expected %s got %s = %s + %s for add 100ths (banker's)");
+ check_binary_op (gnc_numeric_create(5833,10000),
+ gnc_numeric_add(a, b, GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(4) |
+ GNC_RND_ROUND),
+ a, b, "expected %s got %s = %s + %s for add 4 sig figs");
+
+ check_binary_op (gnc_numeric_create(583333,1000000),
+ gnc_numeric_add(a, b, GNC_DENOM_AUTO,
+ GNC_DENOM_SIGFIGS(6) |
+ GNC_RND_ROUND),
+ a, b, "expected %s got %s = %s + %s for add 6 sig figs");
+
check_binary_op (gnc_numeric_create(1,12),
gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_DENOM_EXACT),
a, b, "expected %s got %s = %s - %s for sub exact");
+ /* We should try something trickier for reduce & lcd */
check_binary_op (gnc_numeric_create(1,12),
gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_DENOM_REDUCE),
- a, b, "expected %s got %s = %s - %s for sub least");
+ a, b, "expected %s got %s = %s - %s for sub reduce");
+
+ check_binary_op (gnc_numeric_create(1,12),
+ gnc_numeric_sub(a, b, GNC_DENOM_AUTO, GNC_DENOM_LCD),
+ a, b, "expected %s got %s = %s - %s for sub reduce");
check_binary_op (gnc_numeric_create(8,100),
gnc_numeric_sub(a, b, 100, GNC_RND_ROUND),
- a, b, "expected %s got %s = %s - %s for add 100ths (banker's)");
+ a, b, "expected %s got %s = %s - %s for sub 100ths (banker's)");
#if CHECK_ERRORS_TOO
gnc_numeric c;
@@ -411,6 +429,8 @@
}
}
+/* ======================================================= */
+
static void
check_mult_div (void)
{
@@ -457,8 +477,53 @@
#endif
+ /* Check for math with 2^63 < num*num < 2^64 which previously failed
+ * see http://bugzilla.gnome.org/show_bug.cgi?id=144980
+ */
+ gint64 v = 1000000;
+ a = gnc_numeric_create(1*v, v);
+ b = gnc_numeric_create(10000000*v, v);
+
+ check_binary_op (b,
+ gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_DENOM_LCD),
+ a, b, "expected %s got %s = %s * %s for multiply");
+
+ /* Multiply some random numbers. This test presumes that
+ * RAND_MAX is less than 2^32
+ */
+ int i;
+ for (i=0; i<NREPS; i++)
+ {
+ gint64 deno = 1;
+ gint64 na = rand();
+ gint64 nb = rand();
+ gint64 ne;
+
+ /* avoid overflow; */
+ na /= 2;
+ nb /= 2;
+ ne = na*nb;
+
+ a = gnc_numeric_create(na, deno);
+ b = gnc_numeric_create(nb, deno);
+
+ check_binary_op (gnc_numeric_create(ne,1),
+ gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_DENOM_EXACT),
+ a, b, "expected %s got %s = %s * %s for mult exact");
+ int j;
+ for (j=1; j<31; j++)
+ {
+ a = gnc_numeric_create(na << j, 1<<j);
+ b = gnc_numeric_create(nb << j, 1<<j);
+ check_binary_op (gnc_numeric_create(ne, 1),
+ gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_DENOM_REDUCE),
+ a, b, "expected %s got %s = %s * %s for mult exact");
+ }
+ }
+
}
+/* ======================================================= */
static void
run_test (void)
@@ -467,6 +532,7 @@
check_reduce ();
check_equality_operator ();
check_rounding();
+ check_double();
check_add_subtract();
check_mult_div ();
}
@@ -489,3 +555,5 @@
scm_boot_guile(argc, argv, main_helper, NULL);
return 0;
}
+
+/* ======================== END OF FILE ====================== */
More information about the gnucash-changes
mailing list