00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <ctype.h>
00029 #include <glib.h>
00030 #include "qof.h"
00031 #include "test-stuff.h"
00032 #include "test-engine-stuff.h"
00033 #include "gnc-numeric.h"
00034
00035 #define NREPS 2000
00036
00037 static char *
00038 gnc_numeric_print (gnc_numeric in)
00039 {
00040 char *retval;
00041 if (gnc_numeric_check (in))
00042 {
00043 retval =
00044 g_strdup_printf ("<ERROR> [%" G_GINT64_FORMAT " / %"
00045 G_GINT64_FORMAT "]", in.num, in.denom);
00046 }
00047 else
00048 {
00049 retval =
00050 g_strdup_printf ("[%" G_GINT64_FORMAT " / %" G_GINT64_FORMAT "]",
00051 in.num, in.denom);
00052 }
00053 return retval;
00054 }
00055
00056
00057
00058 static void
00059 check_unary_op (gboolean (*eqtest) (gnc_numeric, gnc_numeric),
00060 gnc_numeric expected,
00061 gnc_numeric actual, gnc_numeric input, const char *errmsg)
00062 {
00063 char *e = gnc_numeric_print (expected);
00064 char *r = gnc_numeric_print (actual);
00065 char *a = gnc_numeric_print (input);
00066 char *str = g_strdup_printf (errmsg, e, r, a);
00067
00068 do_test (eqtest (expected, actual), str);
00069
00070 g_free (a);
00071 g_free (r);
00072 g_free (e);
00073 g_free (str);
00074 }
00075
00076
00077
00078 static void
00079 check_binary_op (gnc_numeric expected,
00080 gnc_numeric actual,
00081 gnc_numeric input_a, gnc_numeric input_b, const char *errmsg)
00082 {
00083 char *e = gnc_numeric_print (expected);
00084 char *r = gnc_numeric_print (actual);
00085 char *a = gnc_numeric_print (input_a);
00086 char *b = gnc_numeric_print (input_b);
00087 char *str = g_strdup_printf (errmsg, e, r, a, b);
00088
00089 do_test (gnc_numeric_eq (expected, actual), str);
00090
00091 g_free (a);
00092 g_free (b);
00093 g_free (r);
00094 g_free (e);
00095 g_free (str);
00096 }
00097
00098
00099
00100 static gboolean
00101 gnc_numeric_unequal (gnc_numeric a, gnc_numeric b)
00102 {
00103 return (0 == gnc_numeric_equal (a, b));
00104 }
00105
00106
00107
00108
00109
00110 static void
00111 check_eq_operator (void)
00112 {
00113 gnc_numeric a = gnc_numeric_create (42, 58);
00114 gnc_numeric b = gnc_numeric_create (42, 58);
00115 gnc_numeric c = gnc_numeric_create (40, 58);
00116
00117
00118 do_test (gnc_numeric_eq (a, a), "expected self-equivalence");
00119 do_test (gnc_numeric_eq (a, b), "expected equivalence");
00120 do_test (0 == gnc_numeric_eq (a, c), "expected inequivalence");
00121 }
00122
00123
00124
00125 static void
00126 check_reduce (void)
00127 {
00128 gnc_numeric one, rone;
00129 gnc_numeric four, rfour;
00130 gnc_numeric val, rval;
00131
00132 one = gnc_numeric_create (1, 1);
00133 rone = gnc_numeric_create (1000000, 1000000);
00134 rone = gnc_numeric_reduce (rone);
00135 do_test (gnc_numeric_eq (one, rone), "reduce to one");
00136
00137 four = gnc_numeric_create (4, 1);
00138 rfour = gnc_numeric_create (480, 120);
00139 rfour = gnc_numeric_reduce (rfour);
00140 do_test (gnc_numeric_eq (four, rfour), "reduce to four");
00141
00142 val = gnc_numeric_create (10023234LL, 334216654LL);
00143 rval = gnc_numeric_reduce (val);
00144 check_unary_op (gnc_numeric_eq,
00145 gnc_numeric_create (5011617, 167108327),
00146 rval,
00147 val, "check_reduce(1) expected %s = %s = reduce(%s)");
00148
00149 val = gnc_numeric_create (17474724864LL, 136048896LL);
00150 rval = gnc_numeric_reduce (val);
00151 check_unary_op (gnc_numeric_eq,
00152 gnc_numeric_create (4 * 17 * 17, 9),
00153 rval,
00154 val, "check_reduce(2) expected %s = %s = reduce(%s)");
00155
00156 val = gnc_numeric_create (1024LL, 1099511627776LL);
00157 rval = gnc_numeric_reduce (val);
00158 check_unary_op (gnc_numeric_eq,
00159 gnc_numeric_create (1, 1024 * 1024 * 1024),
00160 rval,
00161 val, "check_reduce(3): expected %s = %s = reduce(%s)");
00162 }
00163
00164
00165
00166 static void
00167 check_equality_operator (void)
00168 {
00169 int i, m;
00170 gint mult;
00171 gint64 f, deno, numer;
00172 gnc_numeric big, rbig;
00173 gnc_numeric val, mval;
00174 gnc_numeric bval, rval;
00175
00176 numer = 1 << 30;
00177 numer <<= 30;
00178 deno = 1 << 30;
00179 deno <<= 20;
00180 rbig = gnc_numeric_create (numer, deno);
00181
00182 big = gnc_numeric_create (1 << 10, 1);
00183 do_test (gnc_numeric_equal (big, rbig), "equal to billion");
00184
00185 big = gnc_numeric_create (1 << 20, 1 << 10);
00186 do_test (gnc_numeric_equal (big, rbig), "equal to 1<<20/1<<10");
00187
00188 big = gnc_numeric_create (1 << 30, 1 << 20);
00189 do_test (gnc_numeric_equal (big, rbig), "equal to 1<<30/1<<20");
00190
00191 numer = 1 << 30;
00192 numer <<= 30;
00193 deno = 1 << 30;
00194 rbig = gnc_numeric_create (numer, deno);
00195
00196 big = gnc_numeric_create (1 << 30, 1);
00197 do_test (gnc_numeric_equal (big, rbig), "equal to 1<<30");
00198
00199 numer = 1 << 30;
00200 numer <<= 10;
00201 big = gnc_numeric_create (numer, 1 << 10);
00202 do_test (gnc_numeric_equal (big, rbig), "equal to 1<<40/1<<10");
00203
00204 numer <<= 10;
00205 big = gnc_numeric_create (numer, 1 << 20);
00206 do_test (gnc_numeric_equal (big, rbig), "equal to 1<<50/1<<20");
00207
00208
00209 for (i = 0; i < NREPS; i++)
00210 {
00211 deno = rand () / 2;
00212 mult = rand () / 2;
00213 numer = rand () / 2;
00214
00215 val = gnc_numeric_create (numer, deno);
00216 mval = gnc_numeric_create (numer * mult, deno * mult);
00217
00218
00219 bval = gnc_numeric_reduce (val);
00220 rval = gnc_numeric_reduce (mval);
00221 check_unary_op (gnc_numeric_eq,
00222 bval, rval, mval, "expected %s = %s = reduce(%s)");
00223
00224
00225 check_unary_op (gnc_numeric_equal,
00226 val, mval, mval, "expected %s = %s");
00227
00228
00229
00230
00231 mval.denom >>= 1;
00232 mval.num >>= 1;
00233 m = 0;
00234 f = mval.denom;
00235 while (f % 2 == 0)
00236 {
00237 f >>= 1;
00238 m++;
00239 }
00240 if (1 < m)
00241 {
00242 gint64 nn = 1 << (32 - m);
00243 nn <<= 32;
00244 nn += mval.num;
00245 val = gnc_numeric_create (2 * nn, 2 * mval.denom);
00246 check_unary_op (gnc_numeric_unequal,
00247 val, mval, mval, "expected unequality %s != %s");
00248
00249 }
00250 }
00251 }
00252
00253
00254
00255 static void
00256 check_rounding (void)
00257 {
00258 gnc_numeric val;
00259
00260 val = gnc_numeric_create (7, 16);
00261 check_unary_op (gnc_numeric_eq,
00262 gnc_numeric_create (43, 100),
00263 gnc_numeric_convert (val, 100, GNC_HOW_RND_FLOOR),
00264 val, "expected %s = %s = (%s as 100th's floor)");
00265 check_unary_op (gnc_numeric_eq,
00266 gnc_numeric_create (44, 100),
00267 gnc_numeric_convert (val, 100, GNC_HOW_RND_CEIL),
00268 val, "expected %s = %s = (%s as 100th's ceiling)");
00269 check_unary_op (gnc_numeric_eq,
00270 gnc_numeric_create (43, 100),
00271 gnc_numeric_convert (val, 100, GNC_HOW_RND_TRUNC),
00272 val, "expected %s = %s = (%s as 100th's trunc)");
00273 check_unary_op (gnc_numeric_eq,
00274 gnc_numeric_create (44, 100),
00275 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00276 val, "expected %s = %s = (%s as 100th's round)");
00277
00278 val = gnc_numeric_create (1511, 1000);
00279 check_unary_op (gnc_numeric_eq,
00280 gnc_numeric_create (151, 100),
00281 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00282 val, "expected %s = %s = (%s as 100th's round)");
00283
00284 val = gnc_numeric_create (1516, 1000);
00285 check_unary_op (gnc_numeric_eq,
00286 gnc_numeric_create (152, 100),
00287 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00288 val, "expected %s = %s = (%s as 100th's round)");
00289
00290
00291 val = gnc_numeric_create (1515, 1000);
00292 check_unary_op (gnc_numeric_eq,
00293 gnc_numeric_create (152, 100),
00294 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00295 val, "expected %s = %s = (%s as 100th's round)");
00296
00297 val = gnc_numeric_create (1525, 1000);
00298 check_unary_op (gnc_numeric_eq,
00299 gnc_numeric_create (152, 100),
00300 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00301 val, "expected %s = %s = (%s as 100th's round)");
00302
00303 val = gnc_numeric_create (1535, 1000);
00304 check_unary_op (gnc_numeric_eq,
00305 gnc_numeric_create (154, 100),
00306 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00307 val, "expected %s = %s = (%s as 100th's round)");
00308
00309 val = gnc_numeric_create (1545, 1000);
00310 check_unary_op (gnc_numeric_eq,
00311 gnc_numeric_create (154, 100),
00312 gnc_numeric_convert (val, 100, GNC_HOW_RND_ROUND),
00313 val, "expected %s = %s = (%s as 100th's round)");
00314 }
00315
00316
00317
00318 static void
00319 check_double (void)
00320 {
00321 double flo;
00322 gnc_numeric val = gnc_numeric_create (0, 1);
00323
00324 check_unary_op (gnc_numeric_eq,
00325 gnc_numeric_create (112346, 100000),
00326 double_to_gnc_numeric (1.1234567890123,
00327 GNC_DENOM_AUTO,
00328 GNC_HOW_DENOM_SIGFIGS (6) |
00329 GNC_HOW_RND_ROUND),
00330 val, "expected %s = %s double 6 figs");
00331
00332 check_unary_op (gnc_numeric_eq,
00333 gnc_numeric_create (112346, 10000000),
00334 double_to_gnc_numeric (0.011234567890123,
00335 GNC_DENOM_AUTO,
00336 GNC_HOW_DENOM_SIGFIGS (6) |
00337 GNC_HOW_RND_ROUND),
00338 val, "expected %s = %s double 6 figs");
00339
00340 check_unary_op (gnc_numeric_eq,
00341 gnc_numeric_create (112346, 100),
00342 double_to_gnc_numeric (1123.4567890123,
00343 GNC_DENOM_AUTO,
00344 GNC_HOW_DENOM_SIGFIGS (6) |
00345 GNC_HOW_RND_ROUND),
00346 val, "expected %s = %s double 6 figs");
00347 check_unary_op (gnc_numeric_eq,
00348 gnc_numeric_create (112346, 10000000000LL),
00349 double_to_gnc_numeric (1.1234567890123e-5,
00350 GNC_DENOM_AUTO,
00351 GNC_HOW_DENOM_SIGFIGS (6) |
00352 GNC_HOW_RND_ROUND),
00353 val, "expected %s = %s double 6 figs");
00354
00355 flo = gnc_numeric_to_double (gnc_numeric_create (7, 16));
00356 do_test ((0.4375 == flo), "float pt conversion");
00357 }
00358
00359
00360
00361 static void
00362 check_neg (void)
00363 {
00364 gnc_numeric a = gnc_numeric_create (2, 6);
00365 gnc_numeric b = gnc_numeric_create (1, 4);
00366 gnc_numeric c = gnc_numeric_neg (a);
00367 gnc_numeric d = gnc_numeric_neg (b);
00368
00369 check_unary_op (gnc_numeric_eq,
00370 gnc_numeric_create (-2, 6), c,
00371 a, "expected %s = %s = -(%s)");
00372
00373 check_unary_op (gnc_numeric_eq,
00374 gnc_numeric_create (-1, 4), d,
00375 b, "expected %s = %s = -(%s)");
00376
00377 }
00378
00379
00380
00381 static void
00382 check_add_subtract (void)
00383 {
00384 int i;
00385 gnc_numeric a, b, c, d, z;
00386 #if CHECK_ERRORS_TOO
00387 gnc_numeric c;
00388 #endif
00389
00390 a = gnc_numeric_create (2, 6);
00391 b = gnc_numeric_create (1, 4);
00392
00393
00394 check_binary_op (gnc_numeric_create (7, 12),
00395 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00396 GNC_HOW_DENOM_EXACT), a, b,
00397 "expected %s got %s = %s + %s for add exact");
00398
00399 check_binary_op (gnc_numeric_create (58, 100),
00400 gnc_numeric_add (a, b, 100, GNC_HOW_RND_ROUND),
00401 a, b,
00402 "expected %s got %s = %s + %s for add 100ths (banker's)");
00403
00404 check_binary_op (gnc_numeric_create (5833, 10000),
00405 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00406 GNC_HOW_DENOM_SIGFIGS (4) |
00407 GNC_HOW_RND_ROUND),
00408 a, b, "expected %s got %s = %s + %s for add 4 sig figs");
00409
00410 check_binary_op (gnc_numeric_create (583333, 1000000),
00411 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00412 GNC_HOW_DENOM_SIGFIGS (6) |
00413 GNC_HOW_RND_ROUND),
00414 a, b, "expected %s got %s = %s + %s for add 6 sig figs");
00415
00416 check_binary_op (gnc_numeric_create (1, 12),
00417 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00418 GNC_HOW_DENOM_EXACT), a, b,
00419 "expected %s got %s = %s - %s for sub exact");
00420
00421
00422 check_binary_op (gnc_numeric_create (1, 12),
00423 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00424 GNC_HOW_DENOM_REDUCE), a, b,
00425 "expected %s got %s = %s - %s for sub reduce");
00426
00427 check_binary_op (gnc_numeric_create (1, 12),
00428 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00429 GNC_HOW_DENOM_LCD), a, b,
00430 "expected %s got %s = %s - %s for sub reduce");
00431
00432 check_binary_op (gnc_numeric_create (8, 100),
00433 gnc_numeric_sub (a, b, 100, GNC_HOW_RND_ROUND),
00434 a, b,
00435 "expected %s got %s = %s - %s for sub 100ths (banker's)");
00436
00437
00438
00439 c = gnc_numeric_neg (a);
00440 d = gnc_numeric_neg (b);
00441 z = gnc_numeric_zero ();
00442 check_binary_op (c, gnc_numeric_add_fixed (z, c),
00443 z, c, "expected %s got %s = %s + %s for add fixed");
00444
00445 check_binary_op (d, gnc_numeric_add_fixed (z, d),
00446 z, d, "expected %s got %s = %s + %s for add fixed");
00447
00448
00449
00450 a = c;
00451 b = d;
00452
00453 check_binary_op (gnc_numeric_create (-7, 12),
00454 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00455 GNC_HOW_DENOM_EXACT), a, b,
00456 "expected %s got %s = %s + %s for add exact");
00457
00458 check_binary_op (gnc_numeric_create (-58, 100),
00459 gnc_numeric_add (a, b, 100, GNC_HOW_RND_ROUND),
00460 a, b,
00461 "expected %s got %s = %s + %s for add 100ths (banker's)");
00462
00463 check_binary_op (gnc_numeric_create (-5833, 10000),
00464 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00465 GNC_HOW_DENOM_SIGFIGS (4) |
00466 GNC_HOW_RND_ROUND),
00467 a, b, "expected %s got %s = %s + %s for add 4 sig figs");
00468
00469 check_binary_op (gnc_numeric_create (-583333, 1000000),
00470 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00471 GNC_HOW_DENOM_SIGFIGS (6) |
00472 GNC_HOW_RND_ROUND),
00473 a, b, "expected %s got %s = %s + %s for add 6 sig figs");
00474
00475 check_binary_op (gnc_numeric_create (-1, 12),
00476 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00477 GNC_HOW_DENOM_EXACT), a, b,
00478 "expected %s got %s = %s - %s for sub exact");
00479
00480
00481 check_binary_op (gnc_numeric_create (-1, 12),
00482 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00483 GNC_HOW_DENOM_REDUCE), a, b,
00484 "expected %s got %s = %s - %s for sub reduce");
00485
00486 check_binary_op (gnc_numeric_create (-1, 12),
00487 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00488 GNC_HOW_DENOM_LCD), a, b,
00489 "expected %s got %s = %s - %s for sub reduce");
00490
00491 check_binary_op (gnc_numeric_create (-8, 100),
00492 gnc_numeric_sub (a, b, 100, GNC_HOW_RND_ROUND),
00493 a, b,
00494 "expected %s got %s = %s - %s for sub 100ths (banker's)");
00495
00496
00497 #if CHECK_ERRORS_TOO
00498 c = gnc_numeric_add_with_error (a, b, 100, GNC_HOW_RND_ROUND, &err);
00499 printf ("add 100ths/error : %s + %s = %s + (error) %s\n\n",
00500 gnc_numeric_print (a), gnc_numeric_print (b),
00501 gnc_numeric_print (c), gnc_numeric_print (err));
00502
00503 c = gnc_numeric_sub_with_error (a, b, 100, GNC_HOW_RND_FLOOR, &err);
00504 printf ("sub 100ths/error : %s - %s = %s + (error) %s\n\n",
00505 gnc_numeric_print (a), gnc_numeric_print (b),
00506 gnc_numeric_print (c), gnc_numeric_print (err));
00507
00508 #endif
00509
00510
00511
00512 for (i = 0; i < NREPS; i++)
00513 {
00514 gnc_numeric e;
00515 gint64 deno = rand () + 1;
00516 gint64 na = get_random_gint64 ();
00517 gint64 nb = get_random_gint64 ();
00518 gint64 ne;
00519
00520
00521 na /= 2;
00522 nb /= 2;
00523
00524 a = gnc_numeric_create (na, deno);
00525 b = gnc_numeric_create (nb, deno);
00526
00527
00528 ne = na + nb;
00529 e = gnc_numeric_create (ne, deno);
00530 check_binary_op (e,
00531 gnc_numeric_add (a, b, GNC_DENOM_AUTO,
00532 GNC_HOW_DENOM_EXACT), a, b,
00533 "expected %s got %s = %s + %s for exact addition");
00534
00535
00536 ne = na - nb;
00537 e = gnc_numeric_create (ne, deno);
00538 check_binary_op (e,
00539 gnc_numeric_sub (a, b, GNC_DENOM_AUTO,
00540 GNC_HOW_DENOM_EXACT), a, b,
00541 "expected %s got %s = %s - %s for exact subtraction");
00542 }
00543 }
00544
00545
00546
00547 static void
00548 check_mult_div (void)
00549 {
00550 int i, j;
00551 gint64 v;
00552 gnc_numeric c, d;
00553 gnc_numeric amt_a, amt_tot, frac, val_tot, val_a;
00554 gnc_numeric a, b;
00555
00556 a = gnc_numeric_create (-100, 100);
00557 b = gnc_numeric_create (1, 1);
00558 check_binary_op (gnc_numeric_create (-100, 100),
00559 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00560 GNC_HOW_DENOM_EXACT), a, b,
00561 "expected %s got %s = %s / %s div exact");
00562
00563 a = gnc_numeric_create (-100, 100);
00564 b = gnc_numeric_create (-1, 1);
00565 check_binary_op (gnc_numeric_create (100, 100),
00566 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00567 GNC_HOW_DENOM_EXACT), a, b,
00568 "expected %s got %s = %s / %s div exact");
00569
00570 a = gnc_numeric_create (-100, 100);
00571 b = gnc_numeric_create (-1, 1);
00572 check_binary_op (gnc_numeric_create (100, 100),
00573 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00574 GNC_HOW_DENOM_EXACT), a, b,
00575 "expected %s got %s = %s * %s mult exact");
00576
00577 a = gnc_numeric_create (2, 6);
00578 b = gnc_numeric_create (1, 4);
00579
00580 check_binary_op (gnc_numeric_create (2, 24),
00581 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00582 GNC_HOW_DENOM_EXACT), a, b,
00583 "expected %s got %s = %s * %s for mult exact");
00584
00585 check_binary_op (gnc_numeric_create (1, 12),
00586 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00587 GNC_HOW_DENOM_REDUCE), a, b,
00588 "expected %s got %s = %s * %s for mult reduce");
00589
00590 check_binary_op (gnc_numeric_create (8, 100),
00591 gnc_numeric_mul (a, b, 100, GNC_HOW_RND_ROUND),
00592 a, b, "expected %s got %s = %s * %s for mult 100th's");
00593
00594 check_binary_op (gnc_numeric_create (8, 6),
00595 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00596 GNC_HOW_DENOM_EXACT), a, b,
00597 "expected %s got %s = %s / %s for div exact");
00598
00599 check_binary_op (gnc_numeric_create (4, 3),
00600 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00601 GNC_HOW_DENOM_REDUCE), a, b,
00602 "expected %s got %s = %s / %s for div reduce");
00603
00604 check_binary_op (gnc_numeric_create (133, 100),
00605 gnc_numeric_div (a, b, 100, GNC_HOW_RND_ROUND),
00606 a, b, "expected %s got %s = %s * %s for div 100th's");
00607
00608 #if CHECK_ERRORS_TOO
00609 gnc_numeric c;
00610 c = gnc_numeric_mul_with_error (a, b, 100, GNC_HOW_RND_ROUND, &err);
00611 printf ("mul 100ths/error : %s * %s = %s + (error) %s\n\n",
00612 gnc_numeric_print (a), gnc_numeric_print (b),
00613 gnc_numeric_print (c), gnc_numeric_print (err));
00614
00615 c = gnc_numeric_div_with_error (a, b, 100, GNC_HOW_RND_ROUND, &err);
00616 printf ("div 100ths/error : %s / %s = %s + (error) %s\n\n",
00617 gnc_numeric_print (a), gnc_numeric_print (b),
00618 gnc_numeric_print (c), gnc_numeric_print (err));
00619
00620 #endif
00621
00622
00623
00624
00625 v = 1000000;
00626 a = gnc_numeric_create (1 * v, v);
00627 b = gnc_numeric_create (10000000 * v, v);
00628
00629 check_binary_op (b,
00630 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00631 GNC_HOW_DENOM_LCD), a, b,
00632 "expected %s got %s = %s * %s for multiply");
00633
00634
00635
00636
00637 for (i = 0; i < NREPS; i++)
00638 {
00639 gint64 deno = 1;
00640 gint64 na = rand ();
00641 gint64 nb = rand ();
00642 gint64 ne;
00643
00644
00645 na /= 2;
00646 nb /= 2;
00647 ne = na * nb;
00648
00649 a = gnc_numeric_create (na, deno);
00650 b = gnc_numeric_create (nb, deno);
00651
00652 check_binary_op (gnc_numeric_create (ne, 1),
00653 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00654 GNC_HOW_DENOM_EXACT), a, b,
00655 "expected %s got %s = %s * %s for mult exact");
00656
00657
00658 for (j = 1; j < 31; j++)
00659 {
00660 a = gnc_numeric_create (na << j, 1 << j);
00661 b = gnc_numeric_create (nb << j, 1 << j);
00662 check_binary_op (gnc_numeric_create (ne, 1),
00663 gnc_numeric_mul (a, b, GNC_DENOM_AUTO,
00664 GNC_HOW_DENOM_REDUCE), a, b,
00665 "expected %s got %s = %s * %s for mult reduce");
00666 }
00667
00668
00669 b = gnc_numeric_create (deno, nb);
00670
00671 check_binary_op (gnc_numeric_create (ne, 1),
00672 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00673 GNC_HOW_DENOM_EXACT), a, b,
00674 "expected %s got %s = %s / %s for div exact");
00675
00676
00677 na /= 2;
00678 nb /= 2;
00679 ne = na * nb;
00680 for (j = 1; j < 16; j++)
00681 {
00682 a = gnc_numeric_create (na << j, 1 << j);
00683 b = gnc_numeric_create (1 << j, nb << j);
00684 check_binary_op (gnc_numeric_create (ne, 1),
00685 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00686 GNC_HOW_DENOM_REDUCE), a, b,
00687 "expected %s got %s = %s / %s for div reduce");
00688 }
00689 }
00690
00691 a = gnc_numeric_create (782592055622866ULL, 89025);
00692 b = gnc_numeric_create (2222554708930978ULL, 85568);
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 check_binary_op (gnc_numeric_error (GNC_ERROR_OVERFLOW),
00710 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00711 GNC_HOW_RND_NEVER |
00712 GNC_HOW_DENOM_EXACT), a, b,
00713 "expected %s got %s = %s / %s for div exact");
00714
00715 check_binary_op (gnc_numeric_create (338441, 1000000),
00716 gnc_numeric_div (a, b, GNC_DENOM_AUTO,
00717 GNC_HOW_DENOM_SIGFIGS (6) |
00718 GNC_HOW_RND_ROUND), a, b,
00719 "expected %s got %s = %s / %s for div round");
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 a = gnc_numeric_create (-47497125586LL, 82718);
00730 b = gnc_numeric_create (-69100955LL, 55739);
00731 c = gnc_numeric_mul (a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
00732 d = gnc_numeric_create (-32005637020LL, 55739);
00733
00734 check_binary_op (gnc_numeric_create (-102547458LL, 82718),
00735 gnc_numeric_div (c, d, 82718,
00736 GNC_HOW_DENOM_EXACT),
00737 c, d, "expected %s got %s = %s / %s for div round");
00738
00739
00740
00741 check_binary_op (gnc_numeric_error (GNC_ERROR_REMAINDER),
00742 gnc_numeric_div (c, d, 82718,
00743 GNC_HOW_DENOM_EXACT |
00744 GNC_HOW_RND_NEVER), c, d,
00745 "expected %s got %s = %s / %s for div round");
00746
00747
00748 amt_a = gnc_numeric_create (-6005287905LL, 40595);
00749 amt_tot = gnc_numeric_create (-8744187958LL, 40595);
00750 frac = gnc_numeric_div (amt_a, amt_tot,
00751 GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
00752
00753 check_binary_op (gnc_numeric_create (6005287905LL, 8744187958LL),
00754 frac, amt_a, amt_tot,
00755 "expected %s got %s = %s / %s for div reduce");
00756
00757
00758 val_tot = gnc_numeric_create (-4280656418LL, 19873);
00759 val_a = gnc_numeric_mul (frac, val_tot,
00760 gnc_numeric_denom (val_tot),
00761 GNC_HOW_RND_ROUND | GNC_HOW_DENOM_EXACT);
00762 check_binary_op (gnc_numeric_create (-2939846940LL, 19873),
00763 val_a, val_tot, frac,
00764 "expected %s got %s = %s * %s for mult round");
00765
00766 frac = gnc_numeric_create (396226789777979LL, 328758834367851752LL);
00767 val_tot = gnc_numeric_create (467013515494988LL, 100);
00768 val_a = gnc_numeric_mul (frac, val_tot,
00769 gnc_numeric_denom (val_tot),
00770 GNC_HOW_RND_ROUND | GNC_HOW_DENOM_EXACT);
00771 check_binary_op (gnc_numeric_create (562854125307LL, 100),
00772 val_a, val_tot, frac,
00773 "expected %s got %s = %s * %s for mult round");
00774
00775
00776 a = gnc_numeric_create (40066447153986554LL, 4518);
00777 b = gnc_numeric_create (26703286457229LL, 3192);
00778 frac = gnc_numeric_div (a, b,
00779 GNC_DENOM_AUTO,
00780 GNC_HOW_DENOM_SIGFIGS (6) | GNC_HOW_RND_ROUND);
00781
00782 check_binary_op (gnc_numeric_create (106007, 100),
00783 frac, a, b,
00784 "expected %s got %s = %s / %s for mult sigfigs");
00785
00786 }
00787
00788 static void
00789 check_reciprocal (void)
00790 {
00791 gnc_numeric a, b, ans, val;
00792 double flo;
00793
00794 val = gnc_numeric_create (-60, 20);
00795 check_unary_op (gnc_numeric_eq, gnc_numeric_create (-3, -1),
00796 gnc_numeric_convert (val, GNC_DENOM_RECIPROCAL (1),
00797 GNC_HOW_RND_NEVER),
00798 val, "expected %s = %s = (%s as RECIP(1))");
00799
00800 a = gnc_numeric_create (200, 100);
00801 b = gnc_numeric_create (300, 100);
00802
00803
00804 ans = gnc_numeric_add (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00805 check_binary_op (gnc_numeric_create (5, -1),
00806 ans, a, b,
00807 "expected %s got %s = %s + %s for reciprocal");
00808
00809
00810 a = gnc_numeric_create (2, -1);
00811 b = gnc_numeric_create (300, 100);
00812 ans = gnc_numeric_add (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00813 check_binary_op (gnc_numeric_create (5, -1),
00814 ans, a, b,
00815 "expected %s got %s = %s + %s for reciprocal");
00816
00817
00818
00819 a = gnc_numeric_create (2, -1);
00820 b = gnc_numeric_create (300, 100);
00821 ans = gnc_numeric_add (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00822 check_binary_op (gnc_numeric_create (5, -1),
00823 ans, a, b, "expected %s got %s = %s + %s for recirocal");
00824
00825
00826 flo = gnc_numeric_to_double (gnc_numeric_create (5, -1));
00827 do_test ((5.0 == flo), "reciprocal conversion");
00828
00829
00830 a = gnc_numeric_create (2, 1);
00831 b = gnc_numeric_create (2, -1);
00832 do_test ((0 == gnc_numeric_compare (a, b)), " 2 == 2 ");
00833 a = gnc_numeric_create (2, 1);
00834 b = gnc_numeric_create (3, -1);
00835 do_test ((-1 == gnc_numeric_compare (a, b)), " 2 < 3 ");
00836 a = gnc_numeric_create (-2, 1);
00837 b = gnc_numeric_create (2, -1);
00838 do_test ((-1 == gnc_numeric_compare (a, b)), " -2 < 2 ");
00839 a = gnc_numeric_create (2, -1);
00840 b = gnc_numeric_create (3, -1);
00841 do_test ((-1 == gnc_numeric_compare (a, b)), " 2 < 3 ");
00842
00843
00844 a = gnc_numeric_create (2, 1);
00845 b = gnc_numeric_create (2, -1);
00846 do_test (gnc_numeric_equal (a, b), " 2 == 2 ");
00847
00848
00849 a = gnc_numeric_create (2, 1);
00850 b = gnc_numeric_create (3, -1);
00851 ans = gnc_numeric_mul (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00852 check_binary_op (gnc_numeric_create (6, -1),
00853 ans, a, b, "expected %s got %s = %s * %s for recirocal");
00854
00855
00856
00857 a = gnc_numeric_create (-60, 1);
00858 b = gnc_numeric_create (2, -10);
00859 ans = gnc_numeric_div (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00860 check_binary_op (gnc_numeric_create (-3, -1),
00861 ans, a, b, "expected %s got %s = %s / %s for recirocal");
00862
00863
00864 a = gnc_numeric_create (60, 1);
00865 b = gnc_numeric_create (2, -10);
00866 ans = gnc_numeric_div (a, b, GNC_DENOM_RECIPROCAL (1), GNC_HOW_RND_NEVER);
00867 check_binary_op (gnc_numeric_create (3, -1),
00868 ans, a, b, "expected %s got %s = %s / %s for recirocal");
00869
00870
00871 }
00872
00873
00874
00875
00876 static void
00877 run_test (void)
00878 {
00879 check_eq_operator ();
00880 check_reduce ();
00881 check_equality_operator ();
00882 check_rounding ();
00883 check_double ();
00884 check_neg ();
00885 check_add_subtract ();
00886 check_mult_div ();
00887 check_reciprocal ();
00888 }
00889
00890 int
00891 main (int argc, char **argv)
00892 {
00893 qof_init ();
00894 run_test ();
00895
00896 print_test_results ();
00897 exit (get_rv ());
00898 qof_close ();
00899 return get_rv();
00900 }
00901
00902