diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index a461f39523..a71f5adc92 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -551,6 +551,20 @@ xaccTransLookup (const GUID *guid) /********************************************************************\ \********************************************************************/ +/* compute a=b/c unless c is zero ... */ +#define DEVIDE(a,b,c) { \ + if (DEQEPS (0.0, (c), 1.0e-15)) { \ + if (DEQEPS (0.0, (b), 1.0e-6)) { \ + (a) = 0.0; \ + } else { \ + PERR ("zero share price but non-zero value\n"); \ + (a) = (b)/(c); \ + } \ + } else { \ + (a) = (b)/(c); \ + } \ +} + void xaccSplitSetBaseValue (Split *s, double value, const char * base_currency) { @@ -563,29 +577,30 @@ xaccSplitSetBaseValue (Split *s, double value, const char * base_currency) */ if (!(s->acc)) { if (force_double_entry) { + PERR ("split must have a parent\n"); assert (s->acc); } else { - s -> damount = (value / (s->share_price)); + DEVIDE (s -> damount, value, s->share_price); return; } } - /* be more precise -- the value depends on the currency - * we want it expressed in. + /* The value of a split depends on the currency we express the + * value in. This may or may not require a divide. */ if (!safe_strcmp(s->acc->currency, base_currency)) { - s -> damount = (value / (s->share_price)); + DEVIDE (s -> damount, value, s->share_price); } else if (!safe_strcmp(s->acc->security, base_currency)) { s -> damount = value; } else if ((0x0==base_currency) && (0 == force_double_entry)) { - s -> damount = (value / (s->share_price)); + DEVIDE (s -> damount, value, s->share_price); } else { - PERR (" inappropriate base currency %s " - " given split currency=%s and security=%s\n", - base_currency, s->acc->currency, s->acc->security); + PERR ("inappropriate base currency %s " + "given split currency=%s and security=%s\n", + base_currency, s->acc->currency, s->acc->security); return; } } @@ -624,9 +639,9 @@ xaccSplitGetBaseValue (Split *s, const char * base_currency) value = s->damount * s->share_price; } else { - PERR (" inappropriate base currency %s " - " given split currency=%s and security=%s\n", - base_currency, s->acc->currency, s->acc->security); + PERR ("inappropriate base currency %s " + "given split currency=%s and security=%s\n", + base_currency, s->acc->currency, s->acc->security); return 0.0; } return value; @@ -671,8 +686,7 @@ ComputeValue (Split **sarray, Split * skip_me, const char * base_currency) if (!safe_strcmp(s->acc->security, base_currency)) { value += s->damount; } else { - PERR ("Internal Error: " - " inconsistent currencies \n"); + PERR ("inconsistent currencies\n"); assert (0); } } @@ -857,7 +871,7 @@ xaccSplitRebalance (Split *split) base_currency = FindCommonCurrency (trans->splits, ra, rb); if (!base_currency) { - PERR ("Internal Error: no common split currencies \n"); + PERR ("no common split currencies\n"); s = trans->splits[0]; while (s) { if (s->acc) { diff --git a/src/engine/util.h b/src/engine/util.h index 95830b9396..4dc1aa607b 100644 --- a/src/engine/util.h +++ b/src/engine/util.h @@ -124,7 +124,8 @@ size_t dcoresize(); #define isNum(x) (((x)-0x30) < 0) ? 0 : (((x)-0x30) > 9) ? 0 : 1 #define EPS (1.0e-6) -#define DEQ(x,y) (((((x)+EPS)>(y)) ? 1 : 0) && ((((x)-EPS)<(y)) ? 1 : 0)) +#define DEQEPS(x,y,eps) (((((x)+(eps))>(y)) ? 1 : 0) && ((((x)-(eps))<(y)) ? 1 : 0)) +#define DEQ(x,y) DEQEPS(x,y,EPS) #define SAFE_STRCMP(da,db) { \