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 "qofnumeric.h"
00034
00035 #define NREPS 2000
00036
00037 static char *
00038 qof_numeric_print (QofNumeric in)
00039 {
00040 char *retval;
00041 if (qof_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) (QofNumeric, QofNumeric),
00060 QofNumeric expected,
00061 QofNumeric actual, QofNumeric input, const gchar *errmsg)
00062 {
00063 gchar *e = qof_numeric_print (expected);
00064 gchar *r = qof_numeric_print (actual);
00065 gchar *a = qof_numeric_print (input);
00066 gchar *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 (QofNumeric expected,
00080 QofNumeric actual,
00081 QofNumeric input_a, QofNumeric input_b, const gchar *errmsg)
00082 {
00083 gchar *e = qof_numeric_print (expected);
00084 gchar *r = qof_numeric_print (actual);
00085 gchar *a = qof_numeric_print (input_a);
00086 gchar *b = qof_numeric_print (input_b);
00087 gchar *str = g_strdup_printf (errmsg, e, r, a, b);
00088
00089 do_test (qof_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 qof_numeric_unequal (QofNumeric a, QofNumeric b)
00102 {
00103 return (0 == qof_numeric_equal (a, b));
00104 }
00105
00106
00107
00108
00109
00110 static void
00111 check_eq_operator (void)
00112 {
00113 QofNumeric a = qof_numeric_create (42, 58);
00114 QofNumeric b = qof_numeric_create (42, 58);
00115 QofNumeric c = qof_numeric_create (40, 58);
00116
00117
00118 do_test (qof_numeric_eq (a, a), "expected self-equivalence");
00119 do_test (qof_numeric_eq (a, b), "expected equivalence");
00120 do_test (0 == qof_numeric_eq (a, c), "expected inequivalence");
00121 }
00122
00123
00124
00125 static void
00126 check_reduce (void)
00127 {
00128 QofNumeric one, rone;
00129 QofNumeric four, rfour;
00130 QofNumeric val, rval;
00131
00132 one = qof_numeric_create (1, 1);
00133 rone = qof_numeric_create (1000000, 1000000);
00134 rone = qof_numeric_reduce (rone);
00135 do_test (qof_numeric_eq (one, rone), "reduce to one");
00136
00137 four = qof_numeric_create (4, 1);
00138 rfour = qof_numeric_create (480, 120);
00139 rfour = qof_numeric_reduce (rfour);
00140 do_test (qof_numeric_eq (four, rfour), "reduce to four");
00141
00142 val = qof_numeric_create (10023234LL, 334216654LL);
00143 rval = qof_numeric_reduce (val);
00144 check_unary_op (qof_numeric_eq,
00145 qof_numeric_create (5011617, 167108327),
00146 rval,
00147 val, "check_reduce(1) expected %s = %s = reduce(%s)");
00148
00149 val = qof_numeric_create (17474724864LL, 136048896LL);
00150 rval = qof_numeric_reduce (val);
00151 check_unary_op (qof_numeric_eq,
00152 qof_numeric_create (4 * 17 * 17, 9),
00153 rval,
00154 val, "check_reduce(2) expected %s = %s = reduce(%s)");
00155
00156 val = qof_numeric_create (1024LL, 1099511627776LL);
00157 rval = qof_numeric_reduce (val);
00158 check_unary_op (qof_numeric_eq,
00159 qof_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 gint i, m;
00170 gint mult;
00171 gint64 f, deno, numer;
00172 QofNumeric big, rbig;
00173 QofNumeric val, mval;
00174 QofNumeric bval, rval;
00175
00176 numer = 1 << 30;
00177 numer <<= 30;
00178 deno = 1 << 30;
00179 deno <<= 20;
00180 rbig = qof_numeric_create (numer, deno);
00181
00182 big = qof_numeric_create (1 << 10, 1);
00183 do_test (qof_numeric_equal (big, rbig), "equal to billion");
00184
00185 big = qof_numeric_create (1 << 20, 1 << 10);
00186 do_test (qof_numeric_equal (big, rbig), "equal to 1<<20/1<<10");
00187
00188 big = qof_numeric_create (1 << 30, 1 << 20);
00189 do_test (qof_numeric_equal (big, rbig), "equal to 1<<30/1<<20");
00190
00191 numer = 1 << 30;
00192 numer <<= 30;
00193 deno = 1 << 30;
00194 rbig = qof_numeric_create (numer, deno);
00195
00196 big = qof_numeric_create (1 << 30, 1);
00197 do_test (qof_numeric_equal (big, rbig), "equal to 1<<30");
00198
00199 numer = 1 << 30;
00200 numer <<= 10;
00201 big = qof_numeric_create (numer, 1 << 10);
00202 do_test (qof_numeric_equal (big, rbig), "equal to 1<<40/1<<10");
00203
00204 numer <<= 10;
00205 big = qof_numeric_create (numer, 1 << 20);
00206 do_test (qof_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 = qof_numeric_create (numer, deno);
00216 mval = qof_numeric_create (numer * mult, deno * mult);
00217
00218
00219 bval = qof_numeric_reduce (val);
00220 rval = qof_numeric_reduce (mval);
00221 check_unary_op (qof_numeric_eq,
00222 bval, rval, mval, "expected %s = %s = reduce(%s)");
00223
00224
00225 check_unary_op (qof_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 = qof_numeric_create (2 * nn, 2 * mval.denom);
00246 check_unary_op (qof_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 QofNumeric val;
00259
00260 val = qof_numeric_create (7, 16);
00261 check_unary_op (qof_numeric_eq,
00262 qof_numeric_create (43, 100),
00263 qof_numeric_convert (val, 100, QOF_HOW_RND_FLOOR),
00264 val, "expected %s = %s = (%s as 100th's floor)");
00265 check_unary_op (qof_numeric_eq,
00266 qof_numeric_create (44, 100),
00267 qof_numeric_convert (val, 100, QOF_HOW_RND_CEIL),
00268 val, "expected %s = %s = (%s as 100th's ceiling)");
00269 check_unary_op (qof_numeric_eq,
00270 qof_numeric_create (43, 100),
00271 qof_numeric_convert (val, 100, QOF_HOW_RND_TRUNC),
00272 val, "expected %s = %s = (%s as 100th's trunc)");
00273 check_unary_op (qof_numeric_eq,
00274 qof_numeric_create (44, 100),
00275 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00276 val, "expected %s = %s = (%s as 100th's round)");
00277
00278 val = qof_numeric_create (1511, 1000);
00279 check_unary_op (qof_numeric_eq,
00280 qof_numeric_create (151, 100),
00281 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00282 val, "expected %s = %s = (%s as 100th's round)");
00283
00284 val = qof_numeric_create (1516, 1000);
00285 check_unary_op (qof_numeric_eq,
00286 qof_numeric_create (152, 100),
00287 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00288 val, "expected %s = %s = (%s as 100th's round)");
00289
00290
00291 val = qof_numeric_create (1515, 1000);
00292 check_unary_op (qof_numeric_eq,
00293 qof_numeric_create (152, 100),
00294 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00295 val, "expected %s = %s = (%s as 100th's round)");
00296
00297 val = qof_numeric_create (1525, 1000);
00298 check_unary_op (qof_numeric_eq,
00299 qof_numeric_create (152, 100),
00300 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00301 val, "expected %s = %s = (%s as 100th's round)");
00302
00303 val = qof_numeric_create (1535, 1000);
00304 check_unary_op (qof_numeric_eq,
00305 qof_numeric_create (154, 100),
00306 qof_numeric_convert (val, 100, QOF_HOW_RND_ROUND),
00307 val, "expected %s = %s = (%s as 100th's round)");
00308
00309 val = qof_numeric_create (1545, 1000);
00310 check_unary_op (qof_numeric_eq,
00311 qof_numeric_create (154, 100),
00312 qof_numeric_convert (val, 100, QOF_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 gdouble flo;
00322 QofNumeric val = qof_numeric_create (0, 1);
00323
00324 check_unary_op (qof_numeric_eq,
00325 qof_numeric_create (112346, 100000),
00326 qof_numeric_from_double (1.1234567890123,
00327 QOF_DENOM_AUTO,
00328 QOF_HOW_DENOM_SIGFIGS (6) |
00329 QOF_HOW_RND_ROUND),
00330 val, "expected %s = %s double 6 figs");
00331
00332 check_unary_op (qof_numeric_eq,
00333 qof_numeric_create (112346, 10000000),
00334 qof_numeric_from_double (0.011234567890123,
00335 QOF_DENOM_AUTO,
00336 QOF_HOW_DENOM_SIGFIGS (6) |
00337 QOF_HOW_RND_ROUND),
00338 val, "expected %s = %s double 6 figs");
00339
00340 check_unary_op (qof_numeric_eq,
00341 qof_numeric_create (112346, 100),
00342 qof_numeric_from_double (1123.4567890123,
00343 QOF_DENOM_AUTO,
00344 QOF_HOW_DENOM_SIGFIGS (6) |
00345 QOF_HOW_RND_ROUND),
00346 val, "expected %s = %s double 6 figs");
00347 check_unary_op (qof_numeric_eq,
00348 qof_numeric_create (112346, 10000000000LL),
00349 qof_numeric_from_double (1.1234567890123e-5,
00350 QOF_DENOM_AUTO,
00351 QOF_HOW_DENOM_SIGFIGS (6) |
00352 QOF_HOW_RND_ROUND),
00353 val, "expected %s = %s double 6 figs");
00354
00355 flo = qof_numeric_to_double (qof_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 QofNumeric a = qof_numeric_create (2, 6);
00365 QofNumeric b = qof_numeric_create (1, 4);
00366 QofNumeric c = qof_numeric_neg (a);
00367 QofNumeric d = qof_numeric_neg (b);
00368
00369 check_unary_op (qof_numeric_eq,
00370 qof_numeric_create (-2, 6), c,
00371 a, "expected %s = %s = -(%s)");
00372
00373 check_unary_op (qof_numeric_eq,
00374 qof_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 gint i;
00385 QofNumeric a, b, c, d, z;
00386 #if CHECK_ERRORS_TOO
00387 QofNumeric c;
00388 #endif
00389
00390 a = qof_numeric_create (2, 6);
00391 b = qof_numeric_create (1, 4);
00392
00393
00394 check_binary_op (qof_numeric_create (7, 12),
00395 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00396 QOF_HOW_DENOM_EXACT), a, b,
00397 "expected %s got %s = %s + %s for add exact");
00398
00399 check_binary_op (qof_numeric_create (58, 100),
00400 qof_numeric_add (a, b, 100, QOF_HOW_RND_ROUND),
00401 a, b,
00402 "expected %s got %s = %s + %s for add 100ths (banker's)");
00403
00404 check_binary_op (qof_numeric_create (5833, 10000),
00405 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00406 QOF_HOW_DENOM_SIGFIGS (4) |
00407 QOF_HOW_RND_ROUND),
00408 a, b, "expected %s got %s = %s + %s for add 4 sig figs");
00409
00410 check_binary_op (qof_numeric_create (583333, 1000000),
00411 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00412 QOF_HOW_DENOM_SIGFIGS (6) |
00413 QOF_HOW_RND_ROUND),
00414 a, b, "expected %s got %s = %s + %s for add 6 sig figs");
00415
00416 check_binary_op (qof_numeric_create (1, 12),
00417 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00418 QOF_HOW_DENOM_EXACT), a, b,
00419 "expected %s got %s = %s - %s for sub exact");
00420
00421
00422 check_binary_op (qof_numeric_create (1, 12),
00423 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00424 QOF_HOW_DENOM_REDUCE), a, b,
00425 "expected %s got %s = %s - %s for sub reduce");
00426
00427 check_binary_op (qof_numeric_create (1, 12),
00428 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00429 QOF_HOW_DENOM_LCD), a, b,
00430 "expected %s got %s = %s - %s for sub reduce");
00431
00432 check_binary_op (qof_numeric_create (8, 100),
00433 qof_numeric_sub (a, b, 100, QOF_HOW_RND_ROUND),
00434 a, b,
00435 "expected %s got %s = %s - %s for sub 100ths (banker's)");
00436
00437
00438
00439 c = qof_numeric_neg (a);
00440 d = qof_numeric_neg (b);
00441 z = qof_numeric_zero ();
00442 check_binary_op (c, qof_numeric_add_fixed (z, c),
00443 z, c, "expected %s got %s = %s + %s for add fixed");
00444
00445 check_binary_op (d, qof_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 (qof_numeric_create (-7, 12),
00454 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00455 QOF_HOW_DENOM_EXACT), a, b,
00456 "expected %s got %s = %s + %s for add exact");
00457
00458 check_binary_op (qof_numeric_create (-58, 100),
00459 qof_numeric_add (a, b, 100, QOF_HOW_RND_ROUND),
00460 a, b,
00461 "expected %s got %s = %s + %s for add 100ths (banker's)");
00462
00463 check_binary_op (qof_numeric_create (-5833, 10000),
00464 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00465 QOF_HOW_DENOM_SIGFIGS (4) |
00466 QOF_HOW_RND_ROUND),
00467 a, b, "expected %s got %s = %s + %s for add 4 sig figs");
00468
00469 check_binary_op (qof_numeric_create (-583333, 1000000),
00470 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00471 QOF_HOW_DENOM_SIGFIGS (6) |
00472 QOF_HOW_RND_ROUND),
00473 a, b, "expected %s got %s = %s + %s for add 6 sig figs");
00474
00475 check_binary_op (qof_numeric_create (-1, 12),
00476 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00477 QOF_HOW_DENOM_EXACT), a, b,
00478 "expected %s got %s = %s - %s for sub exact");
00479
00480
00481 check_binary_op (qof_numeric_create (-1, 12),
00482 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00483 QOF_HOW_DENOM_REDUCE), a, b,
00484 "expected %s got %s = %s - %s for sub reduce");
00485
00486 check_binary_op (qof_numeric_create (-1, 12),
00487 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00488 QOF_HOW_DENOM_LCD), a, b,
00489 "expected %s got %s = %s - %s for sub reduce");
00490
00491 check_binary_op (qof_numeric_create (-8, 100),
00492 qof_numeric_sub (a, b, 100, QOF_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 = qof_numeric_add_with_error (a, b, 100, QOF_HOW_RND_ROUND, &err);
00499 printf ("add 100ths/error : %s + %s = %s + (error) %s\n\n",
00500 qof_numeric_print (a), qof_numeric_print (b),
00501 qof_numeric_print (c), qof_numeric_print (err));
00502
00503 c = qof_numeric_sub_with_error (a, b, 100, QOf_HOW_RND_FLOOR, &err);
00504 printf ("sub 100ths/error : %s - %s = %s + (error) %s\n\n",
00505 qof_numeric_print (a), qof_numeric_print (b),
00506 qof_numeric_print (c), qof_numeric_print (err));
00507
00508 #endif
00509
00510
00511
00512 for (i = 0; i < NREPS; i++)
00513 {
00514 QofNumeric 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 = qof_numeric_create (na, deno);
00525 b = qof_numeric_create (nb, deno);
00526
00527
00528 ne = na + nb;
00529 e = qof_numeric_create (ne, deno);
00530 check_binary_op (e,
00531 qof_numeric_add (a, b, QOF_DENOM_AUTO,
00532 QOF_HOW_DENOM_EXACT), a, b,
00533 "expected %s got %s = %s + %s for exact addition");
00534
00535
00536 ne = na - nb;
00537 e = qof_numeric_create (ne, deno);
00538 check_binary_op (e,
00539 qof_numeric_sub (a, b, QOF_DENOM_AUTO,
00540 QOF_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 gint i, j;
00551 gint64 v;
00552 QofNumeric c, d;
00553 QofNumeric amt_a, amt_tot, frac, val_tot, val_a;
00554 QofNumeric a, b;
00555
00556 a = qof_numeric_create (-100, 100);
00557 b = qof_numeric_create (1, 1);
00558 check_binary_op (qof_numeric_create (-100, 100),
00559 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00560 QOF_HOW_DENOM_EXACT), a, b,
00561 "expected %s got %s = %s / %s div exact");
00562
00563 a = qof_numeric_create (-100, 100);
00564 b = qof_numeric_create (-1, 1);
00565 check_binary_op (qof_numeric_create (100, 100),
00566 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00567 QOF_HOW_DENOM_EXACT), a, b,
00568 "expected %s got %s = %s / %s div exact");
00569
00570 a = qof_numeric_create (-100, 100);
00571 b = qof_numeric_create (-1, 1);
00572 check_binary_op (qof_numeric_create (100, 100),
00573 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00574 QOF_HOW_DENOM_EXACT), a, b,
00575 "expected %s got %s = %s * %s mult exact");
00576
00577 a = qof_numeric_create (2, 6);
00578 b = qof_numeric_create (1, 4);
00579
00580 check_binary_op (qof_numeric_create (2, 24),
00581 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00582 QOF_HOW_DENOM_EXACT), a, b,
00583 "expected %s got %s = %s * %s for mult exact");
00584
00585 check_binary_op (qof_numeric_create (1, 12),
00586 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00587 QOF_HOW_DENOM_REDUCE), a, b,
00588 "expected %s got %s = %s * %s for mult reduce");
00589
00590 check_binary_op (qof_numeric_create (8, 100),
00591 qof_numeric_mul (a, b, 100, QOF_HOW_RND_ROUND),
00592 a, b, "expected %s got %s = %s * %s for mult 100th's");
00593
00594 check_binary_op (qof_numeric_create (8, 6),
00595 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00596 QOF_HOW_DENOM_EXACT), a, b,
00597 "expected %s got %s = %s / %s for div exact");
00598
00599 check_binary_op (qof_numeric_create (4, 3),
00600 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00601 QOF_HOW_DENOM_REDUCE), a, b,
00602 "expected %s got %s = %s / %s for div reduce");
00603
00604 check_binary_op (qof_numeric_create (133, 100),
00605 qof_numeric_div (a, b, 100, QOF_HOW_RND_ROUND),
00606 a, b, "expected %s got %s = %s * %s for div 100th's");
00607
00608 #if CHECK_ERRORS_TOO
00609 QofNumeric c;
00610 c = qof_numeric_mul_with_error (a, b, 100, QOF_HOW_RND_ROUND, &err);
00611 printf ("mul 100ths/error : %s * %s = %s + (error) %s\n\n",
00612 qof_numeric_print (a), qof_numeric_print (b),
00613 qof_numeric_print (c), qof_numeric_print (err));
00614
00615 c = qof_numeric_div_with_error (a, b, 100, QOF_HOW_RND_ROUND, &err);
00616 printf ("div 100ths/error : %s / %s = %s + (error) %s\n\n",
00617 qof_numeric_print (a), qof_numeric_print (b),
00618 qof_numeric_print (c), qof_numeric_print (err));
00619
00620 #endif
00621
00622
00623
00624
00625 v = 1000000;
00626 a = qof_numeric_create (1 * v, v);
00627 b = qof_numeric_create (10000000 * v, v);
00628
00629 check_binary_op (b,
00630 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00631 QOF_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 = qof_numeric_create (na, deno);
00650 b = qof_numeric_create (nb, deno);
00651
00652 check_binary_op (qof_numeric_create (ne, 1),
00653 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00654 QOF_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 = qof_numeric_create (na << j, 1 << j);
00661 b = qof_numeric_create (nb << j, 1 << j);
00662 check_binary_op (qof_numeric_create (ne, 1),
00663 qof_numeric_mul (a, b, QOF_DENOM_AUTO,
00664 QOF_HOW_DENOM_REDUCE), a, b,
00665 "expected %s got %s = %s * %s for mult reduce");
00666 }
00667
00668
00669 b = qof_numeric_create (deno, nb);
00670
00671 check_binary_op (qof_numeric_create (ne, 1),
00672 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00673 QOF_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 = qof_numeric_create (na << j, 1 << j);
00683 b = qof_numeric_create (1 << j, nb << j);
00684 check_binary_op (qof_numeric_create (ne, 1),
00685 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00686 QOF_HOW_DENOM_REDUCE), a, b,
00687 "expected %s got %s = %s / %s for div reduce");
00688 }
00689 }
00690
00691 a = qof_numeric_create (782592055622866ULL, 89025);
00692 b = qof_numeric_create (2222554708930978ULL, 85568);
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 check_binary_op (qof_numeric_error (QOF_ERROR_OVERFLOW),
00710 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00711 QOF_HOW_RND_NEVER |
00712 QOF_HOW_DENOM_EXACT), a, b,
00713 "expected %s got %s = %s / %s for div exact");
00714
00715 check_binary_op (qof_numeric_create (338441, 1000000),
00716 qof_numeric_div (a, b, QOF_DENOM_AUTO,
00717 QOF_HOW_DENOM_SIGFIGS (6) |
00718 QOF_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 = qof_numeric_create (-47497125586LL, 82718);
00730 b = qof_numeric_create (-69100955LL, 55739);
00731 c = qof_numeric_mul (a, b, QOF_DENOM_AUTO, QOF_HOW_DENOM_EXACT);
00732 d = qof_numeric_create (-32005637020LL, 55739);
00733
00734 check_binary_op (qof_numeric_create (-102547458LL, 82718),
00735 qof_numeric_div (c, d, 82718,
00736 QOF_HOW_DENOM_EXACT),
00737 c, d, "expected %s got %s = %s / %s for div round");
00738
00739
00740
00741 check_binary_op (qof_numeric_error (QOF_ERROR_REMAINDER),
00742 qof_numeric_div (c, d, 82718,
00743 QOF_HOW_DENOM_EXACT |
00744 QOF_HOW_RND_NEVER), c, d,
00745 "expected %s got %s = %s / %s for div round");
00746
00747
00748 amt_a = qof_numeric_create (-6005287905LL, 40595);
00749 amt_tot = qof_numeric_create (-8744187958LL, 40595);
00750 frac = qof_numeric_div (amt_a, amt_tot,
00751 QOF_DENOM_AUTO, QOF_HOW_DENOM_REDUCE);
00752
00753 check_binary_op (qof_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 = qof_numeric_create (-4280656418LL, 19873);
00759 val_a = qof_numeric_mul (frac, val_tot,
00760 qof_numeric_denom (val_tot),
00761 QOF_HOW_RND_ROUND | QOF_HOW_DENOM_EXACT);
00762 check_binary_op (qof_numeric_create (-2939846940LL, 19873),
00763 val_a, val_tot, frac,
00764 "expected %s got %s = %s * %s for mult round");
00765
00766 frac = qof_numeric_create (396226789777979LL, 328758834367851752LL);
00767 val_tot = qof_numeric_create (467013515494988LL, 100);
00768 val_a = qof_numeric_mul (frac, val_tot,
00769 qof_numeric_denom (val_tot),
00770 QOF_HOW_RND_ROUND | QOF_HOW_DENOM_EXACT);
00771 check_binary_op (qof_numeric_create (562854125307LL, 100),
00772 val_a, val_tot, frac,
00773 "expected %s got %s = %s * %s for mult round");
00774
00775
00776 a = qof_numeric_create (40066447153986554LL, 4518);
00777 b = qof_numeric_create (26703286457229LL, 3192);
00778 frac = qof_numeric_div (a, b,
00779 QOF_DENOM_AUTO,
00780 QOF_HOW_DENOM_SIGFIGS (6) | QOF_HOW_RND_ROUND);
00781
00782 check_binary_op (qof_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 QofNumeric a, b, ans, val;
00792 gdouble flo;
00793
00794 val = qof_numeric_create (-60, 20);
00795 check_unary_op (qof_numeric_eq, qof_numeric_create (-3, -1),
00796 qof_numeric_convert (val, QOF_DENOM_RECIPROCAL (1),
00797 QOF_HOW_RND_NEVER),
00798 val, "expected %s = %s = (%s as RECIP(1))");
00799
00800 a = qof_numeric_create (200, 100);
00801 b = qof_numeric_create (300, 100);
00802
00803
00804 ans = qof_numeric_add (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00805 check_binary_op (qof_numeric_create (5, -1),
00806 ans, a, b,
00807 "expected %s got %s = %s + %s for reciprocal");
00808
00809
00810 a = qof_numeric_create (2, -1);
00811 b = qof_numeric_create (300, 100);
00812 ans = qof_numeric_add (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00813 check_binary_op (qof_numeric_create (5, -1),
00814 ans, a, b,
00815 "expected %s got %s = %s + %s for reciprocal");
00816
00817
00818
00819 a = qof_numeric_create (2, -1);
00820 b = qof_numeric_create (300, 100);
00821 ans = qof_numeric_add (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00822 check_binary_op (qof_numeric_create (5, -1),
00823 ans, a, b, "expected %s got %s = %s + %s for recirocal");
00824
00825
00826 flo = qof_numeric_to_double (qof_numeric_create (5, -1));
00827 do_test ((5.0 == flo), "reciprocal conversion");
00828
00829
00830 a = qof_numeric_create (2, 1);
00831 b = qof_numeric_create (2, -1);
00832 do_test ((0 == qof_numeric_compare (a, b)), " 2 == 2 ");
00833 a = qof_numeric_create (2, 1);
00834 b = qof_numeric_create (3, -1);
00835 do_test ((-1 == qof_numeric_compare (a, b)), " 2 < 3 ");
00836 a = qof_numeric_create (-2, 1);
00837 b = qof_numeric_create (2, -1);
00838 do_test ((-1 == qof_numeric_compare (a, b)), " -2 < 2 ");
00839 a = qof_numeric_create (2, -1);
00840 b = qof_numeric_create (3, -1);
00841 do_test ((-1 == qof_numeric_compare (a, b)), " 2 < 3 ");
00842
00843
00844 a = qof_numeric_create (2, 1);
00845 b = qof_numeric_create (2, -1);
00846 do_test (qof_numeric_equal (a, b), " 2 == 2 ");
00847
00848
00849 a = qof_numeric_create (2, 1);
00850 b = qof_numeric_create (3, -1);
00851 ans = qof_numeric_mul (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00852 check_binary_op (qof_numeric_create (6, -1),
00853 ans, a, b, "expected %s got %s = %s * %s for recirocal");
00854
00855
00856
00857 a = qof_numeric_create (-60, 1);
00858 b = qof_numeric_create (2, -10);
00859 ans = qof_numeric_div (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00860 check_binary_op (qof_numeric_create (-3, -1),
00861 ans, a, b, "expected %s got %s = %s / %s for recirocal");
00862
00863
00864 a = qof_numeric_create (60, 1);
00865 b = qof_numeric_create (2, -10);
00866 ans = qof_numeric_div (a, b, QOF_DENOM_RECIPROCAL (1), QOF_HOW_RND_NEVER);
00867 check_binary_op (qof_numeric_create (3, -1),
00868 ans, a, b, "expected %s got %s = %s / %s for recirocal");
00869
00870 }
00871
00872
00873
00874
00875 static void
00876 run_test (void)
00877 {
00878 check_eq_operator ();
00879 check_reduce ();
00880 check_equality_operator ();
00881 check_rounding ();
00882 check_double ();
00883 check_neg ();
00884 check_add_subtract ();
00885 check_mult_div ();
00886 check_reciprocal ();
00887 }
00888
00889 int
00890 main (void)
00891 {
00892 qof_init ();
00893 run_test ();
00894
00895 print_test_results ();
00896 exit (get_rv ());
00897 qof_close ();
00898 return get_rv();
00899 }
00900
00901