mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
add double-precision tests,
add tests of multiplication of random numbers git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@10091 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
7cee0ad628
commit
d58064d16a
@ -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 @@ gnc_numeric_print(gnc_numeric in) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_unary_op (gboolean (*eqtest) (gnc_numeric, gnc_numeric),
|
||||
gnc_numeric expected,
|
||||
@ -54,6 +58,8 @@ check_unary_op (gboolean (*eqtest) (gnc_numeric, gnc_numeric),
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_binary_op (gnc_numeric expected,
|
||||
gnc_numeric actual,
|
||||
@ -76,64 +82,7 @@ check_binary_op (gnc_numeric expected,
|
||||
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 @@ gnc_numeric_unequal (gnc_numeric a, gnc_numeric b)
|
||||
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 @@ check_eq_operator (void)
|
||||
do_test (0 == gnc_numeric_eq(a, c), "expected inequivalence");
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_reduce (void)
|
||||
@ -193,6 +145,8 @@ check_reduce (void)
|
||||
val, "expected %s = %s = reduce(%s)");
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_equality_operator (void)
|
||||
{
|
||||
@ -275,6 +229,8 @@ check_equality_operator (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_rounding (void)
|
||||
{
|
||||
@ -336,12 +292,57 @@ check_rounding (void)
|
||||
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 @@ check_add_subtract (void)
|
||||
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 @@ check_add_subtract (void)
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================= */
|
||||
|
||||
static void
|
||||
check_mult_div (void)
|
||||
{
|
||||
@ -457,8 +477,53 @@ check_mult_div (void)
|
||||
|
||||
#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 @@ run_test (void)
|
||||
check_reduce ();
|
||||
check_equality_operator ();
|
||||
check_rounding();
|
||||
check_double();
|
||||
check_add_subtract();
|
||||
check_mult_div ();
|
||||
}
|
||||
@ -489,3 +555,5 @@ main (int argc, char **argv)
|
||||
scm_boot_guile(argc, argv, main_helper, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ======================== END OF FILE ====================== */
|
||||
|
Loading…
Reference in New Issue
Block a user