Priit Laes' patch for C90 compliance.

* src/engine/Scrub.c
	* src/engine/Scrub2.c
	* src/engine/gnc-numeric.c
	* src/engine/gnc-pricedb.c
	* src/engine/kvp-util.c
	* src/engine/qofid.c
	* src/engine/qofmath128.c
	* src/engine/qofquery.c
	* src/engine/qofsession.c
	* src/engine/test/test-numeric.c
	  Priit Laes' patch for C90 compliance.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@10205 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Derek Atkins 2004-07-20 22:49:58 +00:00
parent 8c83c4fb0f
commit 24b8a65adf
11 changed files with 132 additions and 81 deletions

View File

@ -1,3 +1,17 @@
2004-07-20 Derek Atkins <derek@ihtfp.com>
* src/engine/Scrub.c
* src/engine/Scrub2.c
* src/engine/gnc-numeric.c
* src/engine/gnc-pricedb.c
* src/engine/kvp-util.c
* src/engine/qofid.c
* src/engine/qofmath128.c
* src/engine/qofquery.c
* src/engine/qofsession.c
* src/engine/test/test-numeric.c
Priit Laes' patch for C90 compliance.
2004-07-13 David Montenegro <sunrise2000@comcast.net> 2004-07-13 David Montenegro <sunrise2000@comcast.net>
* src/report/standard-reports/general-ledger.scm: * src/report/standard-reports/general-ledger.scm:

View File

@ -137,6 +137,8 @@ void
xaccTransScrubOrphans (Transaction *trans) xaccTransScrubOrphans (Transaction *trans)
{ {
SplitList *node; SplitList *node;
QofBook *book = NULL;
AccountGroup *root = NULL;
for (node = trans->splits; node; node = node->next) for (node = trans->splits; node; node = node->next)
{ {
Split *split = node->data; Split *split = node->data;
@ -154,8 +156,8 @@ xaccTransScrubOrphans (Transaction *trans)
* XXX we should probably *always* to this, instead of the above loop! * XXX we should probably *always* to this, instead of the above loop!
*/ */
PINFO ("Free Floating Transaction!"); PINFO ("Free Floating Transaction!");
QofBook *book = xaccTransGetBook (trans); book = xaccTransGetBook (trans);
AccountGroup *root = xaccGetAccountGroup (book); root = xaccGetAccountGroup (book);
TransScrubOrphansFast (trans, root); TransScrubOrphansFast (trans, root);
} }
@ -361,6 +363,7 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
Account *parent) Account *parent)
{ {
Split *balance_split = NULL; Split *balance_split = NULL;
QofBook *book = NULL;
gnc_numeric imbalance; gnc_numeric imbalance;
Account *account; Account *account;
SplitList *node, *slist; SplitList *node, *slist;
@ -394,7 +397,7 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root,
/* This should never occur, accounts are always /* This should never occur, accounts are always
* in an account group */ * in an account group */
PERR ("Can't find root account"); PERR ("Can't find root account");
QofBook *book = xaccTransGetBook (trans); book = xaccTransGetBook (trans);
root = xaccGetAccountGroup (book); root = xaccGetAccountGroup (book);
} }
if (NULL == root) if (NULL == root)

View File

@ -156,6 +156,7 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
{ {
gnc_commodity *currency = NULL; gnc_commodity *currency = NULL;
SplitList *snode; SplitList *snode;
GList *node;
gnc_numeric zero = gnc_numeric_zero(); gnc_numeric zero = gnc_numeric_zero();
gnc_numeric value = zero; gnc_numeric value = zero;
@ -211,7 +212,6 @@ xaccLotScrubDoubleBalance (GNCLot *lot)
*/ */
PERR ("Closed lot fails to double-balance !! lot value=%s", PERR ("Closed lot fails to double-balance !! lot value=%s",
gnc_num_dbg_to_string (value)); gnc_num_dbg_to_string (value));
GList *node;
for (node=lot->splits; node; node=node->next) for (node=lot->splits; node; node=node->next)
{ {
Split *s = node->data; Split *s = node->data;

View File

@ -82,6 +82,7 @@ gnc_numeric_check(gnc_numeric in)
static inline gint64 static inline gint64
gnc_numeric_lcd(gnc_numeric a, gnc_numeric b) gnc_numeric_lcd(gnc_numeric a, gnc_numeric b)
{ {
qofint128 lcm;
if(gnc_numeric_check(a) || gnc_numeric_check(b)) if(gnc_numeric_check(a) || gnc_numeric_check(b))
{ {
return GNC_ERROR_ARG; return GNC_ERROR_ARG;
@ -99,7 +100,7 @@ gnc_numeric_lcd(gnc_numeric a, gnc_numeric b)
return b.denom; return b.denom;
} }
qofint128 lcm = lcm128 (a.denom, b.denom); lcm = lcm128 (a.denom, b.denom);
if (lcm.isbig) return GNC_ERROR_ARG; if (lcm.isbig) return GNC_ERROR_ARG;
return lcm.lo; return lcm.lo;
} }
@ -113,6 +114,7 @@ reduce128(qofint128 n, gint64 d)
gint64 num; gint64 num;
gint64 denom; gint64 denom;
gnc_numeric out; gnc_numeric out;
qofint128 red;
t = rem128 (n, d); t = rem128 (n, d);
num = d; num = d;
@ -127,7 +129,7 @@ reduce128(qofint128 n, gint64 d)
} }
/* num now holds the GCD (Greatest Common Divisor) */ /* num now holds the GCD (Greatest Common Divisor) */
qofint128 red = div128 (n, num); red = div128 (n, num);
if (red.isbig) if (red.isbig)
{ {
return gnc_numeric_error (GNC_ERROR_OVERFLOW); return gnc_numeric_error (GNC_ERROR_OVERFLOW);
@ -219,6 +221,7 @@ int
gnc_numeric_compare(gnc_numeric a, gnc_numeric b) gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
{ {
gint64 aa, bb; gint64 aa, bb;
qofint128 l, r;
if(gnc_numeric_check(a) || gnc_numeric_check(b)) if(gnc_numeric_check(a) || gnc_numeric_check(b))
{ {
@ -235,8 +238,8 @@ gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
if ((a.denom > 0) && (b.denom > 0)) if ((a.denom > 0) && (b.denom > 0))
{ {
/* Avoid overflows using 128-bit intermediate math */ /* Avoid overflows using 128-bit intermediate math */
qofint128 l = mult128 (a.num, b.denom); l = mult128 (a.num, b.denom);
qofint128 r = mult128 (b.num, a.denom); r = mult128 (b.num, a.denom);
return cmp128 (l,r); return cmp128 (l,r);
} }
@ -377,18 +380,19 @@ gnc_numeric_add(gnc_numeric a, gnc_numeric b,
* Computing the LCD minimizes likelyhood of overflow * Computing the LCD minimizes likelyhood of overflow
*/ */
gint64 lcd; gint64 lcd;
qofint128 ca, cb, cab;
lcd = gnc_numeric_lcd(a,b); lcd = gnc_numeric_lcd(a,b);
if (GNC_ERROR_ARG == lcd) if (GNC_ERROR_ARG == lcd)
{ {
return gnc_numeric_error(GNC_ERROR_OVERFLOW); return gnc_numeric_error(GNC_ERROR_OVERFLOW);
} }
qofint128 ca = mult128 (a.num, lcd/a.denom); ca = mult128 (a.num, lcd/a.denom);
if (ca.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); if (ca.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
qofint128 cb = mult128 (b.num, lcd/b.denom); cb = mult128 (b.num, lcd/b.denom);
if (cb.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); if (cb.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
qofint128 cab = add128 (ca, cb); cab = add128 (ca, cb);
if (cab.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW); if (cab.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
sum.num = cab.lo; sum.num = cab.lo;
@ -414,12 +418,13 @@ gnc_numeric
gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
gint64 denom, gint how) gint64 denom, gint how)
{ {
gnc_numeric nb;
if(gnc_numeric_check(a) || gnc_numeric_check(b)) if(gnc_numeric_check(a) || gnc_numeric_check(b))
{ {
return gnc_numeric_error(GNC_ERROR_ARG); return gnc_numeric_error(GNC_ERROR_ARG);
} }
gnc_numeric nb = b; nb = b;
nb.num = -nb.num; nb.num = -nb.num;
return gnc_numeric_add (a, nb, denom, how); return gnc_numeric_add (a, nb, denom, how);
} }
@ -552,6 +557,7 @@ gnc_numeric_div(gnc_numeric a, gnc_numeric b,
gint64 denom, gint how) gint64 denom, gint how)
{ {
gnc_numeric quotient; gnc_numeric quotient;
qofint128 nume, deno;
if(gnc_numeric_check(a) || gnc_numeric_check(b)) if(gnc_numeric_check(a) || gnc_numeric_check(b))
{ {
@ -606,8 +612,8 @@ gnc_numeric_div(gnc_numeric a, gnc_numeric b,
sgn = -sgn; sgn = -sgn;
b.num = -b.num; b.num = -b.num;
} }
qofint128 nume = mult128(a.num, b.denom); nume = mult128(a.num, b.denom);
qofint128 deno = mult128(b.num, a.denom); deno = mult128(b.num, a.denom);
/* Try to avoid overflow by removing common factors */ /* Try to avoid overflow by removing common factors */
if (nume.isbig && deno.isbig) if (nume.isbig && deno.isbig)
@ -717,6 +723,7 @@ gnc_numeric_convert(gnc_numeric in, gint64 denom, gint how)
gint denom_neg=0; gint denom_neg=0;
double ratio, logratio; double ratio, logratio;
double sigfigs; double sigfigs;
qofint128 nume, newm;
if(gnc_numeric_check(in)) { if(gnc_numeric_check(in)) {
return gnc_numeric_error(GNC_ERROR_ARG); return gnc_numeric_error(GNC_ERROR_ARG);
@ -813,8 +820,8 @@ gnc_numeric_convert(gnc_numeric in, gint64 denom, gint how)
* out.num = out.num / temp.denom; * out.num = out.num / temp.denom;
* out.denom = denom; * out.denom = denom;
*/ */
qofint128 nume = mult128 (in.num, temp.num); nume = mult128 (in.num, temp.num);
qofint128 newm = div128 (nume, temp.denom); newm = div128 (nume, temp.denom);
remainder = rem128 (nume, temp.denom); remainder = rem128 (nume, temp.denom);
if (newm.isbig) if (newm.isbig)

View File

@ -553,13 +553,14 @@ GNCPriceDB *
gnc_pricedb_create(QofBook * book) gnc_pricedb_create(QofBook * book)
{ {
GNCPriceDB * result; GNCPriceDB * result;
QofCollection *col;
g_return_val_if_fail (book, NULL); g_return_val_if_fail (book, NULL);
/* There can only be one pricedb per book. So if one exits already, /* There can only be one pricedb per book. So if one exits already,
* then use that. Warn user, they shouldn't be creating two ... * then use that. Warn user, they shouldn't be creating two ...
*/ */
QofCollection *col = qof_book_get_collection (book, GNC_ID_PRICEDB); col = qof_book_get_collection (book, GNC_ID_PRICEDB);
result = qof_collection_get_data (col); result = qof_collection_get_data (col);
if (result) if (result)
{ {
@ -584,10 +585,11 @@ destroy_pricedb_currency_hash_data(gpointer key,
{ {
GList *price_list = (GList *) data; GList *price_list = (GList *) data;
GList *node; GList *node;
GNCPrice *p;
for (node = price_list; node; node = node->next) for (node = price_list; node; node = node->next)
{ {
GNCPrice *p = node->data; p = node->data;
p->db = NULL; p->db = NULL;
} }

View File

@ -165,7 +165,7 @@ gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
static KvpFrame * static KvpFrame *
gnc_kvp_bag_get_first (KvpFrame *root, const char * path) gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
{ {
KvpValue *arr; KvpValue *arr, *va;
KvpValueType valtype; KvpValueType valtype;
GList *node; GList *node;
@ -182,7 +182,7 @@ gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
node = kvp_value_get_glist(arr); node = kvp_value_get_glist(arr);
if (NULL == node) return NULL; if (NULL == node) return NULL;
KvpValue *va = node->data; va = node->data;
return kvp_value_get_frame(va); return kvp_value_get_frame(va);
} }

View File

@ -182,8 +182,9 @@ qof_collection_get_type (QofCollection *col)
static void static void
qof_collection_remove_entity (QofEntity *ent) qof_collection_remove_entity (QofEntity *ent)
{ {
QofCollection *col;
if (!ent) return; if (!ent) return;
QofCollection *col = ent->collection; col = ent->collection;
if (!col) return; if (!col) return;
g_hash_table_remove (col->hash_of_entities, &ent->guid); g_hash_table_remove (col->hash_of_entities, &ent->guid);
ent->collection = NULL; ent->collection = NULL;

View File

@ -43,6 +43,13 @@ inline qofint128
mult128 (gint64 a, gint64 b) mult128 (gint64 a, gint64 b)
{ {
qofint128 prod; qofint128 prod;
guint64 a0, a1;
guint64 b0, b1;
guint64 d, d0, d1;
guint64 e, e0, e1;
guint64 f, f0, f1;
guint64 g, g0, g1;
guint64 sum, carry, roll, pmax;
prod.isneg = 0; prod.isneg = 0;
if (0>a) if (0>a)
@ -57,35 +64,35 @@ mult128 (gint64 a, gint64 b)
b = -b; b = -b;
} }
guint64 a1 = a >> 32; a1 = a >> 32;
guint64 a0 = a - (a1<<32); a0 = a - (a1<<32);
guint64 b1 = b >> 32; b1 = b >> 32;
guint64 b0 = b - (b1<<32); b0 = b - (b1<<32);
guint64 d = a0*b0; d = a0*b0;
guint64 d1 = d >> 32; d1 = d >> 32;
guint64 d0 = d - (d1<<32); d0 = d - (d1<<32);
guint64 e = a0*b1; e = a0*b1;
guint64 e1 = e >> 32; e1 = e >> 32;
guint64 e0 = e - (e1<<32); e0 = e - (e1<<32);
guint64 f = a1*b0; f = a1*b0;
guint64 f1 = f >> 32; f1 = f >> 32;
guint64 f0 = f - (f1<<32); f0 = f - (f1<<32);
guint64 g = a1*b1; g = a1*b1;
guint64 g1 = g >> 32; g1 = g >> 32;
guint64 g0 = g - (g1<<32); g0 = g - (g1<<32);
guint64 sum = d1+e0+f0; sum = d1+e0+f0;
guint64 carry = 0; carry = 0;
/* Can't say 1<<32 cause cpp will goof it up; 1ULL<<32 might work */ /* Can't say 1<<32 cause cpp will goof it up; 1ULL<<32 might work */
guint64 roll = 1<<30; roll = 1<<30;
roll <<= 2; roll <<= 2;
guint64 pmax = roll-1; pmax = roll-1;
while (pmax < sum) while (pmax < sum)
{ {
sum -= roll; sum -= roll;
@ -125,7 +132,8 @@ shift128 (qofint128 x)
inline qofint128 inline qofint128
shiftleft128 (qofint128 x) shiftleft128 (qofint128 x)
{ {
guint64 sbit = x.lo & HIBIT; guint64 sbit;
sbit = x.lo & HIBIT;
x.hi <<= 1; x.hi <<= 1;
x.lo <<= 1; x.lo <<= 1;
x.isbig = 0; x.isbig = 0;
@ -174,6 +182,7 @@ inline qofint128
div128 (qofint128 n, gint64 d) div128 (qofint128 n, gint64 d)
{ {
qofint128 quotient; qofint128 quotient;
int i;
guint64 remainder = 0; guint64 remainder = 0;
quotient = n; quotient = n;
@ -184,7 +193,6 @@ div128 (qofint128 n, gint64 d)
} }
/* Use grade-school long division algorithm */ /* Use grade-school long division algorithm */
int i;
for (i=0; i<128; i++) for (i=0; i<128; i++)
{ {
guint64 sbit = HIBIT & quotient.hi; guint64 sbit = HIBIT & quotient.hi;

View File

@ -1216,13 +1216,13 @@ void qof_query_add_guid_match (QofQuery *q, GSList *param_list,
void qof_query_set_book (QofQuery *q, QofBook *book) void qof_query_set_book (QofQuery *q, QofBook *book)
{ {
GSList *slist = NULL;
if (!q || !book) return; if (!q || !book) return;
/* Make sure this book is only in the list once */ /* Make sure this book is only in the list once */
if (g_list_index (q->books, book) == -1) if (g_list_index (q->books, book) == -1)
q->books = g_list_prepend (q->books, book); q->books = g_list_prepend (q->books, book);
GSList *slist = NULL;
g_slist_prepend (slist, QOF_PARAM_GUID); g_slist_prepend (slist, QOF_PARAM_GUID);
g_slist_prepend (slist, QOF_PARAM_BOOK); g_slist_prepend (slist, QOF_PARAM_BOOK);
qof_query_add_guid_match (q, slist, qof_query_add_guid_match (q, slist,

View File

@ -436,6 +436,7 @@ void
qof_session_begin (QofSession *session, const char * book_id, qof_session_begin (QofSession *session, const char * book_id,
gboolean ignore_lock, gboolean create_if_nonexistent) gboolean ignore_lock, gboolean create_if_nonexistent)
{ {
char * p;
if (!session) return; if (!session) return;
ENTER (" sess=%p ignore_lock=%d, book-id=%s", ENTER (" sess=%p ignore_lock=%d, book-id=%s",
@ -471,7 +472,7 @@ qof_session_begin (QofSession *session, const char * book_id,
* "postgres://". Everything before the colon is the access * "postgres://". Everything before the colon is the access
* method. Load the first backend found for that access method. * method. Load the first backend found for that access method.
*/ */
char * p = strchr (book_id, ':'); p = strchr (book_id, ':');
if (p) if (p)
{ {
char * access_method = g_strdup (book_id); char * access_method = g_strdup (book_id);

View File

@ -112,19 +112,22 @@ check_eq_operator (void)
static void static void
check_reduce (void) check_reduce (void)
{ {
gnc_numeric one, rone;
gnc_numeric four, rfour;
gnc_numeric val, rval;
/* Check common factor elimination (needed for equality checks) */ /* Check common factor elimination (needed for equality checks) */
gnc_numeric one = gnc_numeric_create (1,1); one = gnc_numeric_create (1,1);
gnc_numeric rone = gnc_numeric_create (1000000,1000000); rone = gnc_numeric_create (1000000,1000000);
rone = gnc_numeric_reduce (rone); rone = gnc_numeric_reduce (rone);
do_test (gnc_numeric_eq(one, rone), "reduce to one"); do_test (gnc_numeric_eq(one, rone), "reduce to one");
gnc_numeric four = gnc_numeric_create (4,1); four = gnc_numeric_create (4,1);
gnc_numeric rfour = gnc_numeric_create (480,120); rfour = gnc_numeric_create (480,120);
rfour = gnc_numeric_reduce (rfour); rfour = gnc_numeric_reduce (rfour);
do_test (gnc_numeric_eq(four, rfour), "reduce to four"); do_test (gnc_numeric_eq(four, rfour), "reduce to four");
gnc_numeric val = gnc_numeric_create(10023234LL, 334216654LL); val = gnc_numeric_create(10023234LL, 334216654LL);
gnc_numeric rval = gnc_numeric_reduce (val); rval = gnc_numeric_reduce (val);
check_unary_op (gnc_numeric_eq, check_unary_op (gnc_numeric_eq,
gnc_numeric_create (5011617,167108327), gnc_numeric_create (5011617,167108327),
rval, rval,
@ -150,14 +153,20 @@ check_reduce (void)
static void static void
check_equality_operator (void) check_equality_operator (void)
{ {
int i, m;
gint deno, mult, numer;
gint64 f;
gnc_numeric big, rbig;
gnc_numeric val, mval;
gnc_numeric bval, rval;
/* Check equality operator for some large numer/denom values */ /* Check equality operator for some large numer/denom values */
gint64 numer = 1<<30; numer = 1<<30;
numer <<= 30; /* we don't trust cpp to compute 1<<60 correctly */ numer <<= 30; /* we don't trust cpp to compute 1<<60 correctly */
gint64 deno = 1<<30; deno = 1<<30;
deno <<= 20; deno <<= 20;
gnc_numeric rbig = gnc_numeric_create (numer, deno); rbig = gnc_numeric_create (numer, deno);
gnc_numeric big = gnc_numeric_create (1<<10,1); big = gnc_numeric_create (1<<10,1);
do_test (gnc_numeric_equal(big, rbig), "equal to billion"); do_test (gnc_numeric_equal(big, rbig), "equal to billion");
big = gnc_numeric_create (1<<20,1<<10); big = gnc_numeric_create (1<<20,1<<10);
@ -183,20 +192,19 @@ check_equality_operator (void)
big = gnc_numeric_create (numer, 1<<20); big = gnc_numeric_create (numer, 1<<20);
do_test (gnc_numeric_equal(big, rbig), "equal to 1<<50/1<<20"); do_test (gnc_numeric_equal(big, rbig), "equal to 1<<50/1<<20");
int i;
/* We assume RAND_MAX is less that 1<<32 */ /* We assume RAND_MAX is less that 1<<32 */
for (i=0; i<NREPS; i++) for (i=0; i<NREPS; i++)
{ {
gint64 deno = rand() / 2; deno = rand() / 2;
gint64 mult = rand() / 2; mult = rand() / 2;
gint64 numer = rand() / 2; numer = rand() / 2;
gnc_numeric val = gnc_numeric_create (numer, deno); val = gnc_numeric_create (numer, deno);
gnc_numeric mval = gnc_numeric_create (numer*mult, deno*mult); mval = gnc_numeric_create (numer*mult, deno*mult);
/* The reduced version should be equivalent */ /* The reduced version should be equivalent */
gnc_numeric bval = gnc_numeric_reduce (val); bval = gnc_numeric_reduce (val);
gnc_numeric rval = gnc_numeric_reduce (mval); rval = gnc_numeric_reduce (mval);
check_unary_op (gnc_numeric_eq, check_unary_op (gnc_numeric_eq,
bval, rval, mval, "expected %s = %s = reduce(%s)"); bval, rval, mval, "expected %s = %s = reduce(%s)");
@ -209,8 +217,8 @@ check_equality_operator (void)
* might creep in. */ * might creep in. */
mval.denom >>= 1; mval.denom >>= 1;
mval.num >>= 1; mval.num >>= 1;
int m=0; m=0;
gint64 f = mval.denom; f = mval.denom;
while (f%2 == 0) while (f%2 == 0)
{ {
f >>= 1; f >>= 1;
@ -297,6 +305,7 @@ check_rounding (void)
static void static void
check_double (void) check_double (void)
{ {
double flo;
gnc_numeric val = gnc_numeric_create (0,1); gnc_numeric val = gnc_numeric_create (0,1);
check_unary_op (gnc_numeric_eq, check_unary_op (gnc_numeric_eq,
@ -330,7 +339,7 @@ check_double (void)
GNC_HOW_RND_ROUND), GNC_HOW_RND_ROUND),
val, "expected %s = %s double 6 figs"); val, "expected %s = %s double 6 figs");
double flo = gnc_numeric_to_double(gnc_numeric_create(7, 16)); flo = gnc_numeric_to_double(gnc_numeric_create(7, 16));
do_test ((0.4375 == flo), "float pt conversion"); do_test ((0.4375 == flo), "float pt conversion");
} }
@ -359,8 +368,14 @@ check_neg (void)
static void static void
check_add_subtract (void) check_add_subtract (void)
{ {
gnc_numeric a = gnc_numeric_create(2, 6); int i;
gnc_numeric b = gnc_numeric_create(1, 4); gnc_numeric a, b, c, d, z;
#if CHECK_ERRORS_TOO
gnc_numeric c;
#endif
a = gnc_numeric_create(2, 6);
b = gnc_numeric_create(1, 4);
/* Well, actually 14/24 would be acceptable/better in this case */ /* Well, actually 14/24 would be acceptable/better in this case */
check_binary_op (gnc_numeric_create(7,12), check_binary_op (gnc_numeric_create(7,12),
@ -402,9 +417,9 @@ check_add_subtract (void)
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* This test has failed before */ /* This test has failed before */
gnc_numeric c = gnc_numeric_neg (a); c = gnc_numeric_neg (a);
gnc_numeric d = gnc_numeric_neg (b); d = gnc_numeric_neg (b);
gnc_numeric z = gnc_numeric_zero(); z = gnc_numeric_zero();
check_binary_op (c, gnc_numeric_add_fixed(z,c), check_binary_op (c, gnc_numeric_add_fixed(z,c),
z, c, "expected %s got %s = %s + %s for add fixed"); z, c, "expected %s got %s = %s + %s for add fixed");
@ -455,7 +470,6 @@ check_add_subtract (void)
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
#if CHECK_ERRORS_TOO #if CHECK_ERRORS_TOO
gnc_numeric c;
c = gnc_numeric_add_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err); c = gnc_numeric_add_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err);
printf("add 100ths/error : %s + %s = %s + (error) %s\n\n", printf("add 100ths/error : %s + %s = %s + (error) %s\n\n",
gnc_numeric_print(a), gnc_numeric_print(b), gnc_numeric_print(a), gnc_numeric_print(b),
@ -472,7 +486,6 @@ check_add_subtract (void)
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* Add and subtract some random numbers */ /* Add and subtract some random numbers */
int i;
for (i=0; i<NREPS; i++) for (i=0; i<NREPS; i++)
{ {
gnc_numeric e; gnc_numeric e;
@ -509,7 +522,11 @@ check_add_subtract (void)
static void static void
check_mult_div (void) check_mult_div (void)
{ {
int i, j;
gint64 v;
gnc_numeric c, d; gnc_numeric c, d;
gnc_numeric amt_a, amt_tot, frac, val_tot, val_a;
gnc_numeric a = gnc_numeric_create(2, 6); gnc_numeric a = gnc_numeric_create(2, 6);
gnc_numeric b = gnc_numeric_create(1, 4); gnc_numeric b = gnc_numeric_create(1, 4);
@ -556,7 +573,7 @@ check_mult_div (void)
/* Check for math with 2^63 < num*num < 2^64 which previously failed /* Check for math with 2^63 < num*num < 2^64 which previously failed
* see http://bugzilla.gnome.org/show_bug.cgi?id=144980 * see http://bugzilla.gnome.org/show_bug.cgi?id=144980
*/ */
gint64 v = 1000000; v = 1000000;
a = gnc_numeric_create(1*v, v); a = gnc_numeric_create(1*v, v);
b = gnc_numeric_create(10000000*v, v); b = gnc_numeric_create(10000000*v, v);
@ -567,7 +584,6 @@ check_mult_div (void)
/* Multiply some random numbers. This test presumes that /* Multiply some random numbers. This test presumes that
* RAND_MAX is approx 2^32 * RAND_MAX is approx 2^32
*/ */
int i;
for (i=0; i<NREPS; i++) for (i=0; i<NREPS; i++)
{ {
gint64 deno = 1; gint64 deno = 1;
@ -588,7 +604,6 @@ check_mult_div (void)
a, b, "expected %s got %s = %s * %s for mult exact"); a, b, "expected %s got %s = %s * %s for mult exact");
/* Force 128-bit math to come into play */ /* Force 128-bit math to come into play */
int j;
for (j=1; j<31; j++) for (j=1; j<31; j++)
{ {
a = gnc_numeric_create(na << j, 1<<j); a = gnc_numeric_create(na << j, 1<<j);
@ -673,9 +688,9 @@ check_mult_div (void)
c, d, "expected %s got %s = %s / %s for div round"); c, d, "expected %s got %s = %s / %s for div round");
/* A simple irreducible ratio, involving negative numbers */ /* A simple irreducible ratio, involving negative numbers */
gnc_numeric amt_a = gnc_numeric_create (-6005287905LL, 40595); amt_a = gnc_numeric_create (-6005287905LL, 40595);
gnc_numeric amt_tot = gnc_numeric_create (-8744187958LL, 40595); amt_tot = gnc_numeric_create (-8744187958LL, 40595);
gnc_numeric frac = gnc_numeric_div (amt_a, amt_tot, frac = gnc_numeric_div (amt_a, amt_tot,
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE); GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
check_binary_op (gnc_numeric_create(6005287905LL, 8744187958LL), check_binary_op (gnc_numeric_create(6005287905LL, 8744187958LL),
@ -683,8 +698,8 @@ check_mult_div (void)
"expected %s got %s = %s / %s for div reduce"); "expected %s got %s = %s / %s for div reduce");
/* Another overflow-prone condition */ /* Another overflow-prone condition */
gnc_numeric val_tot = gnc_numeric_create (-4280656418LL, 19873); val_tot = gnc_numeric_create (-4280656418LL, 19873);
gnc_numeric val_a = gnc_numeric_mul (frac, val_tot, val_a = gnc_numeric_mul (frac, val_tot,
gnc_numeric_denom(val_tot), gnc_numeric_denom(val_tot),
GNC_HOW_RND_ROUND| GNC_HOW_DENOM_EXACT); GNC_HOW_RND_ROUND| GNC_HOW_DENOM_EXACT);
check_binary_op (gnc_numeric_create(-2939846940LL, 19873), check_binary_op (gnc_numeric_create(-2939846940LL, 19873),