[Gnucash-changes] tweak division
Linas Vepstas
linas at cvs.gnucash.org
Sat Jun 26 01:06:43 EDT 2004
Log Message:
-----------
tweak division
Modified Files:
--------------
gnucash/src/engine:
gnc-numeric.c
Revision Data
-------------
Index: gnc-numeric.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/gnc-numeric.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -Lsrc/engine/gnc-numeric.c -Lsrc/engine/gnc-numeric.c -u -r1.36 -r1.37
--- src/engine/gnc-numeric.c
+++ src/engine/gnc-numeric.c
@@ -516,9 +516,18 @@
}
if ((a.denom > 0) && (b.denom > 0))
{
+ // return (a.num*b.denom == b.num*a.denom);
gncint128 l = mult128 (a.num, b.denom);
gncint128 r = mult128 (b.num, a.denom);
return equal128 (l, r);
+
+#if ALT_WAY_OF_CHECKING_EQUALITY
+ gnc_numeric ra = gnc_numeric_reduce (a);
+ gnc_numeric rb = gnc_numeric_reduce (b);
+ if (ra.denom != rb.denom) return 0;
+ if (ra.num != rb.num) return 0;
+ return 1;
+#endif
}
if ((a.denom < 0) && (b.denom < 0))
{
@@ -782,7 +791,6 @@
gnc_numeric_div(gnc_numeric a, gnc_numeric b,
gint64 denom, gint how) {
gnc_numeric quotient;
- gint64 lcd;
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
return gnc_numeric_error(GNC_ERROR_ARG);
@@ -816,13 +824,37 @@
quotient.num = a.num;
quotient.denom = b.num;
}
- else {
- /* ok, convert to the lcd and compute from there... */
- lcd = gnc_numeric_lcd(a,b);
- quotient.num = a.num*(lcd/a.denom);
- quotient.denom = b.num*(lcd/b.denom);
- // quotient.num = a.num*b.denom;
- // quotient.denom = a.denom*b.num;
+ else
+ {
+ gncint128 nume = mult128(a.num, b.denom);
+ gncint128 deno = mult128(b.num, a.denom);
+ if ((0 == nume.hi) && (0 == deno.hi))
+ {
+ quotient.num = nume.lo;
+ if (nume.isneg) quotient.num = -quotient.num;
+ quotient.denom = deno.lo;
+ }
+ else if (0 == deno.hi)
+ {
+ quotient = reduce128 (nume, deno.lo);
+ }
+ else
+ {
+ /* Try to avoid overflow by working with the LCD */
+ gint64 lcd = gnc_numeric_lcd(a,b);
+ nume = mult128 (a.num, (lcd/a.denom));
+ deno = mult128 (b.num, (lcd/b.denom));
+ if ((0 == nume.hi) && (0 == deno.hi))
+ {
+ quotient.num = nume.lo;
+ if (nume.isneg) quotient.num = -quotient.num;
+ quotient.denom = deno.lo;
+ }
+ else
+ {
+ return gnc_numeric_error (GNC_ERROR_OVERFLOW);
+ }
+ }
}
if(quotient.denom < 0) {
@@ -1382,88 +1414,24 @@
int i;
gint64 v;
- printf("add exact : %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_EXACT)));
-
-
- printf("add least : %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_REDUCE)));
-
- printf("add 100ths (banker's): %s + %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_add(a, b, 100,
- GNC_RND_ROUND)));
-
c = gnc_numeric_add_with_error(a, b, 100, GNC_RND_ROUND, &err);
printf("add 100ths/error : %s + %s = %s + (error) %s\n\n",
gnc_numeric_print(a), gnc_numeric_print(b),
gnc_numeric_print(c),
gnc_numeric_print(err));
- printf("sub exact : %s - %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
- GNC_DENOM_EXACT)));
-
- printf("sub least : %s - %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_sub(a, b,
- GNC_DENOM_AUTO,
- GNC_DENOM_REDUCE)));
-
- printf("sub 100ths : %s - %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_sub(a, b, 100,
- GNC_RND_ROUND)));
-
c = gnc_numeric_sub_with_error(a, b, 100, GNC_RND_FLOOR, &err);
printf("sub 100ths/error : %s - %s = %s + (error) %s\n\n",
gnc_numeric_print(a), gnc_numeric_print(b),
gnc_numeric_print(c),
gnc_numeric_print(err));
- printf("mul exact : %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_EXACT)));
-
- printf("mul least : %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_REDUCE)));
-
- printf("mul 100ths : %s * %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_mul(a, b, 100,
- GNC_RND_ROUND)));
-
c = gnc_numeric_mul_with_error(a, b, 100, GNC_RND_ROUND, &err);
printf("mul 100ths/error : %s * %s = %s + (error) %s\n\n",
gnc_numeric_print(a), gnc_numeric_print(b),
gnc_numeric_print(c),
gnc_numeric_print(err));
- printf("div exact : %s / %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_div(a, b, GNC_DENOM_AUTO,
- GNC_DENOM_EXACT)));
-
- printf("div least : %s / %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_div(a, b, GNC_DENOM_AUTO,
- GNC_DENOM_REDUCE)));
-
- printf("div 100ths : %s / %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_div(a, b, 100,
- GNC_RND_ROUND)));
-
c = gnc_numeric_div_with_error(a, b, 100, GNC_RND_ROUND, &err);
printf("div 100ths/error : %s / %s = %s + (error) %s\n\n",
gnc_numeric_print(a), gnc_numeric_print(b),
@@ -1473,49 +1441,6 @@
printf("7/16 as float: %e\n",
gnc_numeric_to_double(gnc_numeric_create(7, 16)));
- printf("7/16 as 100ths (floor): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
- 100, GNC_RND_FLOOR)));
- printf("7/16 as 100ths (ceil): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
- 100, GNC_RND_CEIL)));
- printf("7/16 as 100ths (trunc): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
- 100, GNC_RND_TRUNC)));
- printf("7/16 as 100ths (round): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
- 100, GNC_RND_ROUND)));
-
- printf("1511/1000 as 1/100 (round): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1511, 1000),
- 100, GNC_RND_ROUND)));
- printf("1516/1000 as 1/100 (round): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1516, 1000),
- 100, GNC_RND_ROUND)));
- printf("1515/1000 as 1/100 (round): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1515, 1000),
- 100, GNC_RND_ROUND)));
- printf("1525/1000 as 1/100 (round): %s\n",
- gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1525, 1000),
- 100, GNC_RND_ROUND)));
-
- printf("100023234 / 334216654 reduced: %s\n",
- gnc_numeric_print(gnc_numeric_reduce(gnc_numeric_create(10023234LL,
- 334216654LL))));
- printf("2^10*3^10*17^2 / 2^8*3^12 reduced: %s\n",
- gnc_numeric_print
- (gnc_numeric_reduce(gnc_numeric_create(17474724864LL,
- 136048896LL))));
- printf("1024 / 1024^4 reduced: %s\n",
- gnc_numeric_print
- (gnc_numeric_reduce(gnc_numeric_create(1024LL,
- 1099511627776LL))));
- printf("reducing 100,000 times:\n\n");
- for(i = 0; i < 100000; i++) {
- gnc_numeric_reduce(gnc_numeric_create(17474724864LL,
- 136048896LL));
- }
-
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,
@@ -1556,7 +1481,17 @@
gnc_numeric_print(a), gnc_numeric_print(b),
gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_DENOM_LCD)));
+ printf("multiply (EXACT): %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_EXACT)));
+
+ printf("multiply (REDUCE): %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_REDUCE)));
+
return 0;
}
#endif
+
+/* ======================== END OF FILE =================== */
More information about the gnucash-changes
mailing list