A 'Numeric' value represents a number in rational form, with a 64-bit integer as numerator and denominator. Rationals are ideal for many uses, such as performing exact, roundoff-error-free addition and multiplication, but 64-bit rationals do not have the dynamic range of floating point numbers.
Files | |
file | qofnumeric.h |
An exact-rational-number library for QOF. | |
Modules | |
Math128 | |
Data Structures | |
struct | _QofNumeric |
Standard Arguments to most functions | |
Most of the QofNumeric arithmetic functions take two arguments in addition to their numeric args: 'denom', which is the denominator to use in the output QofNumeric object, and 'how'. which describes how the arithmetic result is to be converted to that denominator. This combination of output denominator and rounding policy allows the results of financial and other rational computations to be properly rounded to the appropriate units. Valid values for denom are: QOF_DENOM_AUTO -- compute denominator exactly integer n -- Force the denominator of the result to be this integer QOF_DENOM_RECIPROCAL -- Use 1/n as the denominator (???huh???) Valid values for 'how' are bitwise combinations of zero or one "rounding instructions" with zero or one "denominator types". Valid rounding instructions are: QOF_HOW_RND_FLOOR QOF_HOW_RND_CEIL QOF_HOW_RND_TRUNC QOF_HOW_RND_PROMOTE QOF_HOW_RND_ROUND_HALF_DOWN QOF_HOW_RND_ROUND_HALF_UP QOF_HOW_RND_ROUND QOF_HOW_RND_NEVER The denominator type specifies how to compute a denominator if QOF_DENOM_AUTO is specified as the 'denom'. Valid denominator types are: QOF_HOW_DENOM_EXACT QOF_HOW_DENOM_REDUCE QOF_HOW_DENOM_LCD QOF_HOW_DENOM_FIXED QOF_HOW_DENOM_SIGFIGS(N) To use traditional rational-number operational semantics (all results are exact and are reduced to relatively-prime fractions) pass the argument QOF_DENOM_AUTO as 'denom' and QOF_HOW_DENOM_REDUCE| QOF_HOW_RND_NEVER as 'how'.
To enforce strict financial semantics (such that all operands must have the same denominator as each other and as the result), use QOF_DENOM_AUTO as 'denom' and QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER as 'how'. | |
enum | { QOF_HOW_RND_FLOOR = 0x01, QOF_HOW_RND_CEIL = 0x02, QOF_HOW_RND_TRUNC = 0x03, QOF_HOW_RND_PROMOTE = 0x04, QOF_HOW_RND_ROUND_HALF_DOWN = 0x05, QOF_HOW_RND_ROUND_HALF_UP = 0x06, QOF_HOW_RND_ROUND = 0x07, QOF_HOW_RND_NEVER = 0x08 } |
Rounding/Truncation modes for operations. More... | |
enum | { QOF_HOW_DENOM_EXACT = 0x10, QOF_HOW_DENOM_REDUCE = 0x20, QOF_HOW_DENOM_LCD = 0x30, QOF_HOW_DENOM_FIXED = 0x40, QOF_HOW_DENOM_SIGFIG = 0x50 } |
enum | QofNumericErrorCode { QOF_ERROR_OK = 0, QOF_ERROR_ARG = -1, QOF_ERROR_OVERFLOW = -2, QOF_ERROR_DENOM_DIFF = -3, QOF_ERROR_REMAINDER = -4 } |
#define | QOF_NUMERIC_RND_MASK 0x0000000f |
bitmasks for HOW flags. | |
#define | QOF_NUMERIC_DENOM_MASK 0x000000f0 |
#define | QOF_NUMERIC_SIGFIGS_MASK 0x0000ff00 |
#define | QOF_HOW_DENOM_SIGFIGS(n) ( ((( n ) & 0xff) << 8) | QOF_HOW_DENOM_SIGFIG) |
#define | QOF_HOW_GET_SIGFIGS(a) ( (( a ) & 0xff00 ) >> 8) |
#define | QOF_DENOM_AUTO 0 |
#define | QOF_DENOM_RECIPROCAL(a) (- ( a )) |
Constructors | |
static QofNumeric | qof_numeric_create (gint64 num, gint64 denom) |
static QofNumeric | qof_numeric_zero (void) |
QofNumeric | qof_numeric_from_double (gdouble in, gint64 denom, gint how) |
gboolean | qof_numeric_from_string (const gchar *str, QofNumeric *n) |
QofNumeric | qof_numeric_error (QofNumericErrorCode error_code) |
Value Accessors | |
static gint64 | qof_numeric_num (QofNumeric a) |
static gint64 | qof_numeric_denom (QofNumeric a) |
gdouble | qof_numeric_to_double (QofNumeric in) |
gchar * | qof_numeric_to_string (QofNumeric n) |
gchar * | qof_numeric_dbg_to_string (QofNumeric n) |
Comparisons and Predicates | |
QofNumericErrorCode | qof_numeric_check (QofNumeric a) |
gint | qof_numeric_compare (QofNumeric a, QofNumeric b) |
gboolean | qof_numeric_zero_p (QofNumeric a) |
gboolean | qof_numeric_negative_p (QofNumeric a) |
gboolean | qof_numeric_positive_p (QofNumeric a) |
gboolean | qof_numeric_eq (QofNumeric a, QofNumeric b) |
gboolean | qof_numeric_equal (QofNumeric a, QofNumeric b) |
gint | qof_numeric_same (QofNumeric a, QofNumeric b, gint64 denom, gint how) |
Arithmetic Operations | |
QofNumeric | qof_numeric_add (QofNumeric a, QofNumeric b, gint64 denom, gint how) |
QofNumeric | qof_numeric_sub (QofNumeric a, QofNumeric b, gint64 denom, gint how) |
QofNumeric | qof_numeric_mul (QofNumeric a, QofNumeric b, gint64 denom, gint how) |
QofNumeric | qof_numeric_div (QofNumeric x, QofNumeric y, gint64 denom, gint how) |
QofNumeric | qof_numeric_neg (QofNumeric a) |
QofNumeric | qof_numeric_abs (QofNumeric a) |
static QofNumeric | qof_numeric_add_fixed (QofNumeric a, QofNumeric b) |
static QofNumeric | qof_numeric_sub_fixed (QofNumeric a, QofNumeric b) |
Arithmetic Functions with Exact Error Returns | |
QofNumeric | qof_numeric_add_with_error (QofNumeric a, QofNumeric b, gint64 denom, gint how, QofNumeric *error) |
QofNumeric | qof_numeric_sub_with_error (QofNumeric a, QofNumeric b, gint64 denom, gint how, QofNumeric *error) |
QofNumeric | qof_numeric_mul_with_error (QofNumeric a, QofNumeric b, gint64 denom, gint how, QofNumeric *error) |
QofNumeric | qof_numeric_div_with_error (QofNumeric a, QofNumeric b, gint64 denom, gint how, QofNumeric *error) |
Change Denominator | |
QofNumeric | qof_numeric_convert (QofNumeric in, gint64 denom, gint how) |
QofNumeric | qof_numeric_convert_with_error (QofNumeric in, gint64 denom, gint how, QofNumeric *error) |
QofNumeric | qof_numeric_reduce (QofNumeric in) |
Deprecated, backwards-compatible definitions | |
#define | QOF_RND_FLOOR QOF_HOW_RND_FLOOR |
#define | QOF_RND_CEIL QOF_HOW_RND_CEIL |
#define | QOF_RND_TRUNC QOF_HOW_RND_TRUNC |
#define | QOF_RND_PROMOTE QOF_HOW_RND_PROMOTE |
#define | QOF_RND_ROUND_HALF_DOWN QOF_HOW_RND_ROUND_HALF_DOWN |
#define | QOF_RND_ROUND_HALF_UP QOF_HOW_RND_ROUND_HALF_UP |
#define | QOF_RND_ROUND QOF_HOW_RND_ROUND |
#define | QOF_RND_NEVER QOF_HOW_RND_NEVER |
#define | QOF_DENOM_EXACT QOF_HOW_DENOM_EXACT |
#define | QOF_DENOM_REDUCE QOF_HOW_DENOM_REDUCE |
#define | QOF_DENOM_LCD QOF_HOW_DENOM_LCD |
#define | QOF_DENOM_FIXED QOF_HOW_DENOM_FIXED |
#define | QOF_DENOM_SIGFIG QOF_HOW_DENOM_SIGFIG |
#define | QOF_DENOM_SIGFIGS(X) QOF_HOW_DENOM_SIGFIGS(X) |
#define | QOF_NUMERIC_GET_SIGFIGS(X) QOF_HOW_GET_SIGFIGS(X) |
Typedefs | |
typedef struct _QofNumeric | QofNumeric |
A rational-number type. |
#define QOF_DENOM_AUTO 0 |
Values that can be passed as the 'denom' argument. The include a positive number n to be used as the denominator of the output value. Other possibilities include the list below: Compute an appropriate denominator automatically. Flags in the 'how' argument will specify how to compute the denominator.
Definition at line 231 of file qofnumeric.h.
#define QOF_DENOM_RECIPROCAL | ( | a | ) | (- ( a )) |
Use the value 1/n as the denominator of the output value.
Definition at line 234 of file qofnumeric.h.
#define QOF_HOW_DENOM_SIGFIGS | ( | n | ) | ( ((( n ) & 0xff) << 8) | QOF_HOW_DENOM_SIGFIG) |
Build a 'how' value that will generate a denominator that will keep at least n significant figures in the result.
Definition at line 203 of file qofnumeric.h.
#define QOF_NUMERIC_RND_MASK 0x0000000f |
bitmasks for HOW flags.
bits 8-15 of 'how' are reserved for the number of significant digits to use in the output with QOF_HOW_DENOM_SIGFIG
Definition at line 116 of file qofnumeric.h.
typedef struct _QofNumeric QofNumeric |
A rational-number type.
This is a rational number, defined by numerator and denominator.
Definition at line 61 of file qofnumeric.h.
anonymous enum |
Rounding/Truncation modes for operations.
Rounding instructions control how fractional parts in the specified denominator affect the result. For example, if a computed result is "3/4" but the specified denominator for the return value is 2, should the return value be "1/2" or "2/2"?
Possible rounding instructions are:
Definition at line 129 of file qofnumeric.h.
00130 { 00132 QOF_HOW_RND_FLOOR = 0x01, 00133 00135 QOF_HOW_RND_CEIL = 0x02, 00136 00138 QOF_HOW_RND_TRUNC = 0x03, 00139 00141 QOF_HOW_RND_PROMOTE = 0x04, 00142 00146 QOF_HOW_RND_ROUND_HALF_DOWN = 0x05, 00147 00151 QOF_HOW_RND_ROUND_HALF_UP = 0x06, 00152 00158 QOF_HOW_RND_ROUND = 0x07, 00159 00163 QOF_HOW_RND_NEVER = 0x08 00164 };
anonymous enum |
How to compute a denominator, or'ed into the "how" field.
Definition at line 167 of file qofnumeric.h.
00168 { 00174 QOF_HOW_DENOM_EXACT = 0x10, 00175 00181 QOF_HOW_DENOM_REDUCE = 0x20, 00182 00186 QOF_HOW_DENOM_LCD = 0x30, 00187 00192 QOF_HOW_DENOM_FIXED = 0x40, 00193 00197 QOF_HOW_DENOM_SIGFIG = 0x50 00198 };
enum QofNumericErrorCode |
Error codes
Definition at line 207 of file qofnumeric.h.
00208 { 00209 QOF_ERROR_OK = 0, 00210 QOF_ERROR_ARG = -1, 00211 QOF_ERROR_OVERFLOW = -2, 00214 QOF_ERROR_DENOM_DIFF = -3, 00215 00218 QOF_ERROR_REMAINDER = -4 00219 } QofNumericErrorCode;
QofNumeric qof_numeric_abs | ( | QofNumeric | a | ) |
Return the absolute value of the argument
Definition at line 650 of file qofnumeric.c.
00651 { 00652 if (qof_numeric_check (a)) 00653 return qof_numeric_error (QOF_ERROR_ARG); 00654 return qof_numeric_create (ABS (a.num), a.denom); 00655 }
QofNumeric qof_numeric_add | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how | |||
) |
Return a+b.
Definition at line 300 of file qofnumeric.c.
00301 { 00302 QofNumeric sum; 00303 00304 if (qof_numeric_check (a) || qof_numeric_check (b)) 00305 return qof_numeric_error (QOF_ERROR_ARG); 00306 00307 if ((denom == QOF_DENOM_AUTO) && 00308 (how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_FIXED) 00309 { 00310 if (a.denom == b.denom) 00311 denom = a.denom; 00312 else if (b.num == 0) 00313 { 00314 denom = a.denom; 00315 b.denom = a.denom; 00316 } 00317 else if (a.num == 0) 00318 { 00319 denom = b.denom; 00320 a.denom = b.denom; 00321 } 00322 else 00323 return qof_numeric_error (QOF_ERROR_DENOM_DIFF); 00324 } 00325 00326 if (a.denom < 0) 00327 { 00328 a.num *= -a.denom; /* BUG: overflow not handled. */ 00329 a.denom = 1; 00330 } 00331 00332 if (b.denom < 0) 00333 { 00334 b.num *= -b.denom; /* BUG: overflow not handled. */ 00335 b.denom = 1; 00336 } 00337 00338 /* Get an exact answer.. same denominator is the common case. */ 00339 if (a.denom == b.denom) 00340 { 00341 sum.num = a.num + b.num; /* BUG: overflow not handled. */ 00342 sum.denom = a.denom; 00343 } 00344 else 00345 { 00346 /* We want to do this: 00347 * sum.num = a.num*b.denom + b.num*a.denom; 00348 * sum.denom = a.denom*b.denom; 00349 * but the multiply could overflow. 00350 * Computing the LCD minimizes likelihood of overflow 00351 */ 00352 gint64 lcd; 00353 QofInt128 ca, cb, cab; 00354 00355 lcd = qof_numeric_lcd (a, b); 00356 if (QOF_ERROR_ARG == lcd) 00357 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00358 ca = mult128 (a.num, lcd / a.denom); 00359 if (ca.isbig) 00360 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00361 cb = mult128 (b.num, lcd / b.denom); 00362 if (cb.isbig) 00363 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00364 cab = add128 (ca, cb); 00365 if (cab.isbig) 00366 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00367 sum.num = cab.lo; 00368 if (cab.isneg) 00369 sum.num = -sum.num; 00370 sum.denom = lcd; 00371 } 00372 00373 if ((denom == QOF_DENOM_AUTO) && 00374 ((how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_LCD)) 00375 { 00376 denom = qof_numeric_lcd (a, b); 00377 how = how & QOF_NUMERIC_RND_MASK; 00378 } 00379 00380 return qof_numeric_convert (sum, denom, how); 00381 }
static QofNumeric qof_numeric_add_fixed | ( | QofNumeric | a, | |
QofNumeric | b | |||
) | [inline, static] |
Shortcut for common case: QofNumeric_add(a, b, QOF_DENOM_AUTO, QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
Definition at line 411 of file qofnumeric.h.
00412 { 00413 return qof_numeric_add (a, b, QOF_DENOM_AUTO, 00414 QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER); 00415 }
QofNumeric qof_numeric_add_with_error | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how, | |||
QofNumeric * | error | |||
) |
The same as QofNumeric_add, but uses 'error' for accumulating conversion roundoff error.
Definition at line 1014 of file qofnumeric.c.
01016 { 01017 01018 QofNumeric sum = qof_numeric_add (a, b, denom, how); 01019 QofNumeric exact = qof_numeric_add (a, b, QOF_DENOM_AUTO, 01020 QOF_HOW_DENOM_REDUCE); 01021 QofNumeric err = qof_numeric_sub (sum, exact, QOF_DENOM_AUTO, 01022 QOF_HOW_DENOM_REDUCE); 01023 01024 if (error) 01025 *error = err; 01026 return sum; 01027 }
QofNumericErrorCode qof_numeric_check | ( | QofNumeric | a | ) | [inline] |
Check for error signal in value. Returns QOF_ERROR_OK (==0) if the number appears to be valid, otherwise it returns the type of error. Error values always have a denominator of zero.
Definition at line 44 of file qofnumeric.c.
00045 { 00046 if (in.denom != 0) 00047 return QOF_ERROR_OK; 00048 else if (in.num) 00049 { 00050 if ((0 < in.num) || (-4 > in.num)) 00051 in.num = (gint64) QOF_ERROR_OVERFLOW; 00052 return (QofNumericErrorCode) in.num; 00053 } 00054 else 00055 return QOF_ERROR_ARG; 00056 }
gint qof_numeric_compare | ( | QofNumeric | a, | |
QofNumeric | b | |||
) |
Returns 1 if a>b, -1 if b>a, 0 if a == b
Definition at line 174 of file qofnumeric.c.
00175 { 00176 gint64 aa, bb; 00177 QofInt128 l, r; 00178 00179 if (qof_numeric_check (a) || qof_numeric_check (b)) 00180 return 0; 00181 00182 if (a.denom == b.denom) 00183 { 00184 if (a.num == b.num) 00185 return 0; 00186 if (a.num > b.num) 00187 return 1; 00188 return -1; 00189 } 00190 00191 if ((a.denom > 0) && (b.denom > 0)) 00192 { 00193 /* Avoid overflows using 128-bit intermediate math */ 00194 l = mult128 (a.num, b.denom); 00195 r = mult128 (b.num, a.denom); 00196 return cmp128 (l, r); 00197 } 00198 00199 if (a.denom < 0) 00200 a.denom *= -1; 00201 if (b.denom < 0) 00202 b.denom *= -1; 00203 00204 /* BUG: Possible overflow here.. Also, doesn't properly deal with 00205 * reciprocal denominators. 00206 */ 00207 aa = a.num * a.denom; 00208 bb = b.num * b.denom; 00209 00210 if (aa == bb) 00211 return 0; 00212 if (aa > bb) 00213 return 1; 00214 return -1; 00215 }
QofNumeric qof_numeric_convert | ( | QofNumeric | in, | |
gint64 | denom, | |||
gint | how | |||
) |
Change the denominator of a QofNumeric value to the specified denominator under standard arguments 'denom' and 'how'.
Definition at line 662 of file qofnumeric.c.
00663 { 00664 QofNumeric out; 00665 QofNumeric temp; 00666 gint64 temp_bc; 00667 gint64 temp_a; 00668 gint64 remainder; 00669 gint64 sign; 00670 gint denom_neg = 0; 00671 gdouble ratio, logratio; 00672 gdouble sigfigs; 00673 QofInt128 nume, newm; 00674 00675 temp.num = 0; 00676 temp.denom = 0; 00677 00678 if (qof_numeric_check (in)) 00679 return qof_numeric_error (QOF_ERROR_ARG); 00680 00681 if (denom == QOF_DENOM_AUTO) 00682 { 00683 switch (how & QOF_NUMERIC_DENOM_MASK) 00684 { 00685 default: 00686 case QOF_HOW_DENOM_LCD: /* LCD is meaningless with AUTO in here */ 00687 case QOF_HOW_DENOM_EXACT: 00688 return in; 00689 break; 00690 00691 case QOF_HOW_DENOM_REDUCE: 00692 /* reduce the input to a relatively-prime fraction */ 00693 return qof_numeric_reduce (in); 00694 break; 00695 00696 case QOF_HOW_DENOM_FIXED: 00697 if (in.denom != denom) 00698 return qof_numeric_error (QOF_ERROR_DENOM_DIFF); 00699 else 00700 return in; 00701 break; 00702 00703 case QOF_HOW_DENOM_SIGFIG: 00704 ratio = fabs (qof_numeric_to_double (in)); 00705 if (ratio < 10e-20) 00706 logratio = 0; 00707 else 00708 { 00709 logratio = log10 (ratio); 00710 logratio = ((logratio > 0.0) ? 00711 (floor (logratio) + 1.0) : (ceil (logratio))); 00712 } 00713 sigfigs = QOF_HOW_GET_SIGFIGS (how); 00714 00715 if (sigfigs - logratio >= 0) 00716 denom = (gint64) (pow (10, sigfigs - logratio)); 00717 else 00718 denom = -((gint64) (pow (10, logratio - sigfigs))); 00719 00720 how = how & ~QOF_HOW_DENOM_SIGFIG & ~QOF_NUMERIC_SIGFIGS_MASK; 00721 break; 00722 } 00723 } 00724 00725 /* Make sure we need to do the work */ 00726 if (in.denom == denom) 00727 return in; 00728 if (in.num == 0) 00729 { 00730 out.num = 0; 00731 out.denom = denom; 00732 return out; 00733 } 00734 00735 /* If the denominator of the input value is negative, get rid of that. */ 00736 if (in.denom < 0) 00737 { 00738 in.num = in.num * (-in.denom); /* BUG: overflow not handled. */ 00739 in.denom = 1; 00740 } 00741 00742 sign = (in.num < 0) ? -1 : 1; 00743 00744 /* If the denominator is less than zero, we are to interpret it as 00745 * the reciprocal of its magnitude. */ 00746 if (denom < 0) 00747 { 00748 00749 /* XXX FIXME: use 128-bit math here ... */ 00750 denom = -denom; 00751 denom_neg = 1; 00752 temp_a = (in.num < 0) ? -in.num : in.num; 00753 temp_bc = in.denom * denom; /* BUG: overflow not handled. */ 00754 remainder = temp_a % temp_bc; 00755 out.num = temp_a / temp_bc; 00756 out.denom = -denom; 00757 } 00758 else 00759 { 00760 /* Do all the modulo and int division on positive values to make 00761 * things a little clearer. Reduce the fraction denom/in.denom to 00762 * help with range errors */ 00763 temp.num = denom; 00764 temp.denom = in.denom; 00765 temp = qof_numeric_reduce (temp); 00766 00767 /* Symbolically, do the following: 00768 * out.num = in.num * temp.num; 00769 * remainder = out.num % temp.denom; 00770 * out.num = out.num / temp.denom; 00771 * out.denom = denom; 00772 */ 00773 nume = mult128 (in.num, temp.num); 00774 newm = div128 (nume, temp.denom); 00775 remainder = rem128 (nume, temp.denom); 00776 00777 if (newm.isbig) 00778 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00779 00780 out.num = newm.lo; 00781 out.denom = denom; 00782 } 00783 00784 if (remainder) 00785 { 00786 switch (how & QOF_NUMERIC_RND_MASK) 00787 { 00788 case QOF_HOW_RND_FLOOR: 00789 if (sign < 0) 00790 out.num = out.num + 1; 00791 break; 00792 00793 case QOF_HOW_RND_CEIL: 00794 if (sign > 0) 00795 out.num = out.num + 1; 00796 break; 00797 00798 case QOF_HOW_RND_TRUNC: 00799 break; 00800 00801 case QOF_HOW_RND_PROMOTE: 00802 out.num = out.num + 1; 00803 break; 00804 00805 case QOF_HOW_RND_ROUND_HALF_DOWN: 00806 if (denom_neg) 00807 { 00808 if ((2 * remainder) > in.denom * denom) 00809 out.num = out.num + 1; 00810 } 00811 else if ((2 * remainder) > temp.denom) 00812 out.num = out.num + 1; 00813 /* check that 2*remainder didn't over-flow */ 00814 else if (((2 * remainder) < remainder) && 00815 (remainder > (temp.denom / 2))) 00816 out.num = out.num + 1; 00817 break; 00818 00819 case QOF_HOW_RND_ROUND_HALF_UP: 00820 if (denom_neg) 00821 { 00822 if ((2 * remainder) >= in.denom * denom) 00823 out.num = out.num + 1; 00824 } 00825 else if ((2 * remainder) >= temp.denom) 00826 out.num = out.num + 1; 00827 /* check that 2*remainder didn't over-flow */ 00828 else if (((2 * remainder) < remainder) && 00829 (remainder >= (temp.denom / 2))) 00830 out.num = out.num + 1; 00831 break; 00832 00833 case QOF_HOW_RND_ROUND: 00834 if (denom_neg) 00835 { 00836 if ((2 * remainder) > in.denom * denom) 00837 out.num = out.num + 1; 00838 else if ((2 * remainder) == in.denom * denom) 00839 { 00840 if (out.num % 2) 00841 out.num = out.num + 1; 00842 } 00843 } 00844 else 00845 { 00846 if ((2 * remainder) > temp.denom) 00847 out.num = out.num + 1; 00848 /* check that 2*remainder didn't over-flow */ 00849 else if (((2 * remainder) < remainder) && 00850 (remainder > (temp.denom / 2))) 00851 { 00852 out.num = out.num + 1; 00853 } 00854 else if ((2 * remainder) == temp.denom) 00855 { 00856 if (out.num % 2) 00857 out.num = out.num + 1; 00858 } 00859 /* check that 2*remainder didn't over-flow */ 00860 else if (((2 * remainder) < remainder) && 00861 (remainder == (temp.denom / 2))) 00862 { 00863 if (out.num % 2) 00864 out.num = out.num + 1; 00865 } 00866 } 00867 break; 00868 00869 case QOF_HOW_RND_NEVER: 00870 return qof_numeric_error (QOF_ERROR_REMAINDER); 00871 break; 00872 } 00873 } 00874 00875 out.num = (sign > 0) ? out.num : (-out.num); 00876 00877 return out; 00878 }
QofNumeric qof_numeric_convert_with_error | ( | QofNumeric | in, | |
gint64 | denom, | |||
gint | how, | |||
QofNumeric * | error | |||
) |
Same as QofNumeric_convert, but return a remainder value for accumulating conversion error.
static QofNumeric qof_numeric_create | ( | gint64 | num, | |
gint64 | denom | |||
) | [inline, static] |
Make a QofNumeric from numerator and denominator
Definition at line 243 of file qofnumeric.h.
00244 { 00245 QofNumeric out; 00246 out.num = num; 00247 out.denom = denom; 00248 return out; 00249 }
gchar* qof_numeric_dbg_to_string | ( | QofNumeric | n | ) |
Convert to string. Uses a static, non-thread-safe buffer. For internal use only.
Definition at line 1103 of file qofnumeric.c.
01104 { 01105 static gchar buff[1000]; 01106 static gchar *p = buff; 01107 gint64 tmpnum = n.num; 01108 gint64 tmpdenom = n.denom; 01109 01110 p += 100; 01111 if (p - buff >= 1000) 01112 p = buff; 01113 01114 sprintf (p, "%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, 01115 tmpdenom); 01116 01117 return p; 01118 }
static gint64 qof_numeric_denom | ( | QofNumeric | a | ) | [inline, static] |
QofNumeric qof_numeric_div | ( | QofNumeric | x, | |
QofNumeric | y, | |||
gint64 | denom, | |||
gint | how | |||
) |
Division. Note that division can overflow, in the following sense: if we write x=a/b and y=c/d then x/y = (a*d)/(b*c) If, after eliminating all common factors between the numerator (a*d) and the denominator (b*c), then if either the numerator and/or the denominator are *still* greater than 2^63, then the division has overflowed.
Definition at line 516 of file qofnumeric.c.
00517 { 00518 QofNumeric quotient; 00519 QofInt128 nume, deno; 00520 00521 if (qof_numeric_check (a) || qof_numeric_check (b)) 00522 return qof_numeric_error (QOF_ERROR_ARG); 00523 00524 if ((denom == QOF_DENOM_AUTO) && 00525 (how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_FIXED) 00526 { 00527 if (a.denom == b.denom) 00528 denom = a.denom; 00529 else if (a.denom == 0) 00530 denom = b.denom; 00531 else 00532 return qof_numeric_error (QOF_ERROR_DENOM_DIFF); 00533 } 00534 00535 if (a.denom < 0) 00536 { 00537 a.num *= -a.denom; /* BUG: overflow not handled. */ 00538 a.denom = 1; 00539 } 00540 00541 if (b.denom < 0) 00542 { 00543 b.num *= -b.denom; /* BUG: overflow not handled. */ 00544 b.denom = 1; 00545 } 00546 00547 if (a.denom == b.denom) 00548 { 00549 quotient.num = a.num; 00550 quotient.denom = b.num; 00551 } 00552 else 00553 { 00554 gint64 sgn = 1; 00555 if (0 > a.num) 00556 { 00557 sgn = -sgn; 00558 a.num = -a.num; 00559 } 00560 if (0 > b.num) 00561 { 00562 sgn = -sgn; 00563 b.num = -b.num; 00564 } 00565 nume = mult128 (a.num, b.denom); 00566 deno = mult128 (b.num, a.denom); 00567 00568 /* Try to avoid overflow by removing common factors */ 00569 if (nume.isbig && deno.isbig) 00570 { 00571 QofNumeric ra = qof_numeric_reduce (a); 00572 QofNumeric rb = qof_numeric_reduce (b); 00573 gint64 gcf_nume = gcf64 (ra.num, rb.num); 00574 gint64 gcf_deno = gcf64 (rb.denom, ra.denom); 00575 00576 nume = mult128 (ra.num / gcf_nume, rb.denom / gcf_deno); 00577 deno = mult128 (rb.num / gcf_nume, ra.denom / gcf_deno); 00578 } 00579 00580 if ((0 == nume.isbig) && (0 == deno.isbig)) 00581 { 00582 quotient.num = sgn * nume.lo; 00583 quotient.denom = deno.lo; 00584 goto dive_done; 00585 } 00586 else if (0 == deno.isbig) 00587 { 00588 quotient = reduce128 (nume, deno.lo); 00589 if (0 == qof_numeric_check (quotient)) 00590 { 00591 quotient.num *= sgn; 00592 goto dive_done; 00593 } 00594 } 00595 00596 /* If rounding allowed, then shift until there's no 00597 * more overflow. The conversion at the end will fix 00598 * things up for the final value. */ 00599 if ((how & QOF_NUMERIC_RND_MASK) == QOF_HOW_RND_NEVER) 00600 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00601 while (nume.isbig || deno.isbig) 00602 { 00603 nume = shift128 (nume); 00604 deno = shift128 (deno); 00605 } 00606 quotient.num = sgn * nume.lo; 00607 quotient.denom = deno.lo; 00608 if (0 == quotient.denom) 00609 { 00610 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00611 } 00612 } 00613 00614 if (quotient.denom < 0) 00615 { 00616 quotient.num = -quotient.num; 00617 quotient.denom = -quotient.denom; 00618 } 00619 00620 dive_done: 00621 if ((denom == QOF_DENOM_AUTO) && 00622 ((how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_LCD)) 00623 { 00624 denom = qof_numeric_lcd (a, b); 00625 how = how & QOF_NUMERIC_RND_MASK; 00626 } 00627 00628 return qof_numeric_convert (quotient, denom, how); 00629 }
QofNumeric qof_numeric_div_with_error | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how, | |||
QofNumeric * | error | |||
) |
The same as QofNumeric_div, but uses error for accumulating conversion roundoff error.
Definition at line 1071 of file qofnumeric.c.
01073 { 01074 QofNumeric quot = qof_numeric_div (a, b, denom, how); 01075 QofNumeric exact = qof_numeric_div (a, b, QOF_DENOM_AUTO, 01076 QOF_HOW_DENOM_REDUCE); 01077 QofNumeric err = qof_numeric_sub (quot, exact, 01078 QOF_DENOM_AUTO, QOF_HOW_DENOM_REDUCE); 01079 if (error) 01080 *error = err; 01081 return quot; 01082 }
gboolean qof_numeric_eq | ( | QofNumeric | a, | |
QofNumeric | b | |||
) |
Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and denominator)
Definition at line 223 of file qofnumeric.c.
gboolean qof_numeric_equal | ( | QofNumeric | a, | |
QofNumeric | b | |||
) |
Equivalence predicate: Returns TRUE (1) if a and b represent the same number. That is, return TRUE if the ratios, when reduced by eliminating common factors, are identical.
Definition at line 233 of file qofnumeric.c.
00234 { 00235 QofInt128 l, r; 00236 00237 if ((a.denom == b.denom) && (a.denom > 0)) 00238 return (a.num == b.num); 00239 if ((a.denom > 0) && (b.denom > 0)) 00240 { 00241 // return (a.num*b.denom == b.num*a.denom); 00242 l = mult128 (a.num, b.denom); 00243 r = mult128 (b.num, a.denom); 00244 return equal128 (l, r); 00245 00246 #if ALT_WAY_OF_CHECKING_EQUALITY 00247 QofNumeric ra = QofNumeric_reduce (a); 00248 QofNumeric rb = QofNumeric_reduce (b); 00249 if (ra.denom != rb.denom) 00250 return 0; 00251 if (ra.num != rb.num) 00252 return 0; 00253 return 1; 00254 #endif 00255 } 00256 if ((a.denom < 0) && (b.denom < 0)) 00257 { 00258 l = mult128 (a.num, -a.denom); 00259 r = mult128 (b.num, -b.denom); 00260 return equal128 (l, r); 00261 } 00262 else 00263 { 00264 /* BUG: One of the numbers has a reciprocal denom, and the other 00265 does not. I just don't know to handle this case in any 00266 reasonably overflow-proof yet simple way. So, this funtion 00267 will simply get it wrong whenever the three multiplies 00268 overflow 64-bits. -CAS */ 00269 if (a.denom < 0) 00270 return ((a.num * -a.denom * b.denom) == b.num); 00271 else 00272 return (a.num == (b.num * a.denom * -b.denom)); 00273 } 00274 return ((a.num * b.denom) == (a.denom * b.num)); 00275 }
QofNumeric qof_numeric_error | ( | QofNumericErrorCode | error_code | ) |
Create a QofNumeric object that signals the error condition noted by error_code, rather than a number.
Definition at line 1004 of file qofnumeric.c.
01005 { 01006 return qof_numeric_create (error_code, 0LL); 01007 }
QofNumeric qof_numeric_from_double | ( | gdouble | in, | |
gint64 | denom, | |||
gint | how | |||
) |
Convert a floating-point number to a QofNumeric. Both 'denom' and 'how' are used as in arithmetic, but QOF_DENOM_AUTO is not recognized; a denominator must be specified either explicitctly or through sigfigs.
Definition at line 919 of file qofnumeric.c.
00920 { 00921 QofNumeric out; 00922 gint64 int_part = 0; 00923 gdouble frac_part; 00924 gint64 frac_int = 0; 00925 gdouble logval; 00926 gdouble sigfigs; 00927 00928 if ((denom == QOF_DENOM_AUTO) && (how & QOF_HOW_DENOM_SIGFIG)) 00929 { 00930 if (fabs (in) < 10e-20) 00931 logval = 0; 00932 else 00933 { 00934 logval = log10 (fabs (in)); 00935 logval = ((logval > 0.0) ? 00936 (floor (logval) + 1.0) : (ceil (logval))); 00937 } 00938 sigfigs = QOF_HOW_GET_SIGFIGS (how); 00939 if (sigfigs - logval >= 0) 00940 denom = (gint64) (pow (10, sigfigs - logval)); 00941 else 00942 denom = -((gint64) (pow (10, logval - sigfigs))); 00943 00944 how = how & ~QOF_HOW_DENOM_SIGFIG & ~QOF_NUMERIC_SIGFIGS_MASK; 00945 } 00946 00947 int_part = (gint64) (floor (fabs (in))); 00948 frac_part = in - (double) int_part; 00949 00950 int_part = int_part * denom; 00951 frac_part = frac_part * (double) denom; 00952 00953 switch (how & QOF_NUMERIC_RND_MASK) 00954 { 00955 case QOF_HOW_RND_FLOOR: 00956 frac_int = (gint64) floor (frac_part); 00957 break; 00958 00959 case QOF_HOW_RND_CEIL: 00960 frac_int = (gint64) ceil (frac_part); 00961 break; 00962 00963 case QOF_HOW_RND_TRUNC: 00964 frac_int = (gint64) frac_part; 00965 break; 00966 00967 case QOF_HOW_RND_ROUND: 00968 case QOF_HOW_RND_ROUND_HALF_UP: 00969 frac_int = (gint64) rint (frac_part); 00970 break; 00971 00972 case QOF_HOW_RND_NEVER: 00973 frac_int = (gint64) floor (frac_part); 00974 if (frac_part != (double) frac_int) 00975 { 00976 /* signal an error */ 00977 } 00978 break; 00979 } 00980 00981 out.num = int_part + frac_int; 00982 out.denom = denom; 00983 return out; 00984 }
gboolean qof_numeric_from_string | ( | const gchar * | str, | |
QofNumeric * | n | |||
) |
Read a QofNumeric from str, skipping any leading whitespace. Return TRUE on success and store the resulting value in "n". Return NULL on error.
Definition at line 1121 of file qofnumeric.c.
01122 { 01123 size_t num_read; 01124 gint64 tmpnum; 01125 gint64 tmpdenom; 01126 01127 if (!str) 01128 return FALSE; 01129 01130 #ifdef QOF_DEPRECATED 01131 /* must use "<" here because %n's effects aren't well defined */ 01132 if (sscanf (str, " " QOF_SCANF_LLD "/" QOF_SCANF_LLD "%n", 01133 &tmpnum, &tmpdenom, &num_read) < 2) 01134 { 01135 return FALSE; 01136 } 01137 #else 01138 tmpnum = strtoll (str, NULL, 0); 01139 str = strchr (str, '/'); 01140 if (!str) 01141 return FALSE; 01142 str++; 01143 tmpdenom = strtoll (str, NULL, 0); 01144 num_read = strspn (str, "0123456789"); 01145 #endif 01146 n->num = tmpnum; 01147 n->denom = tmpdenom; 01148 return TRUE; 01149 }
QofNumeric qof_numeric_mul | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how | |||
) |
Multiply a times b, returning the product. An overflow may occur if the result of the multiplication can't be represented as a ratio of 64-bit int's after removing common factors.
Definition at line 405 of file qofnumeric.c.
00406 { 00407 QofNumeric product, result; 00408 QofInt128 bignume, bigdeno; 00409 00410 if (qof_numeric_check (a) || qof_numeric_check (b)) 00411 return qof_numeric_error (QOF_ERROR_ARG); 00412 00413 if ((denom == QOF_DENOM_AUTO) && 00414 (how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_FIXED) 00415 { 00416 if (a.denom == b.denom) 00417 denom = a.denom; 00418 else if (b.num == 0) 00419 denom = a.denom; 00420 else if (a.num == 0) 00421 denom = b.denom; 00422 else 00423 return qof_numeric_error (QOF_ERROR_DENOM_DIFF); 00424 } 00425 00426 if ((denom == QOF_DENOM_AUTO) && 00427 ((how & QOF_NUMERIC_DENOM_MASK) == QOF_HOW_DENOM_LCD)) 00428 { 00429 denom = qof_numeric_lcd (a, b); 00430 how = how & QOF_NUMERIC_RND_MASK; 00431 } 00432 00433 if (a.denom < 0) 00434 { 00435 a.num *= -a.denom; /* BUG: overflow not handled. */ 00436 a.denom = 1; 00437 } 00438 00439 if (b.denom < 0) 00440 { 00441 b.num *= -b.denom; /* BUG: overflow not handled. */ 00442 b.denom = 1; 00443 } 00444 00445 bignume = mult128 (a.num, b.num); 00446 bigdeno = mult128 (a.denom, b.denom); 00447 product.num = a.num * b.num; 00448 product.denom = a.denom * b.denom; 00449 00450 /* If it looks to be overflowing, try to reduce the fraction ... */ 00451 if (bignume.isbig || bigdeno.isbig) 00452 { 00453 gint64 tmp; 00454 00455 a = qof_numeric_reduce (a); 00456 b = qof_numeric_reduce (b); 00457 tmp = a.num; 00458 a.num = b.num; 00459 b.num = tmp; 00460 a = qof_numeric_reduce (a); 00461 b = qof_numeric_reduce (b); 00462 bignume = mult128 (a.num, b.num); 00463 bigdeno = mult128 (a.denom, b.denom); 00464 product.num = a.num * b.num; 00465 product.denom = a.denom * b.denom; 00466 } 00467 00468 /* If it its still overflowing, and rounding is allowed then round */ 00469 if (bignume.isbig || bigdeno.isbig) 00470 { 00471 /* If rounding allowed, then shift until there's no 00472 * more overflow. The conversion at the end will fix 00473 * things up for the final value. Else overflow. */ 00474 if ((how & QOF_NUMERIC_RND_MASK) == QOF_HOW_RND_NEVER) 00475 { 00476 if (bigdeno.isbig) 00477 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00478 product = reduce128 (bignume, product.denom); 00479 if (qof_numeric_check (product)) 00480 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00481 } 00482 else 00483 { 00484 while (bignume.isbig || bigdeno.isbig) 00485 { 00486 bignume = shift128 (bignume); 00487 bigdeno = shift128 (bigdeno); 00488 } 00489 product.num = bignume.lo; 00490 if (bignume.isneg) 00491 product.num = -product.num; 00492 00493 product.denom = bigdeno.lo; 00494 if (0 == product.denom) 00495 return qof_numeric_error (QOF_ERROR_OVERFLOW); 00496 } 00497 } 00498 00499 #if 0 /* currently, product denom won't ever be zero */ 00500 if (product.denom < 0) 00501 { 00502 product.num = -product.num; 00503 product.denom = -product.denom; 00504 } 00505 #endif 00506 00507 result = qof_numeric_convert (product, denom, how); 00508 return result; 00509 }
QofNumeric qof_numeric_mul_with_error | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how, | |||
QofNumeric * | error | |||
) |
The same as QofNumeric_mul, but uses error for accumulating conversion roundoff error.
Definition at line 1052 of file qofnumeric.c.
01054 { 01055 QofNumeric prod = qof_numeric_mul (a, b, denom, how); 01056 QofNumeric exact = qof_numeric_mul (a, b, QOF_DENOM_AUTO, 01057 QOF_HOW_DENOM_REDUCE); 01058 QofNumeric err = qof_numeric_sub (prod, exact, QOF_DENOM_AUTO, 01059 QOF_HOW_DENOM_REDUCE); 01060 if (error) 01061 *error = err; 01062 return prod; 01063 }
QofNumeric qof_numeric_neg | ( | QofNumeric | a | ) |
Negate the argument
Definition at line 637 of file qofnumeric.c.
00638 { 00639 if (qof_numeric_check (a)) 00640 return qof_numeric_error (QOF_ERROR_ARG); 00641 return qof_numeric_create (-a.num, a.denom); 00642 }
gboolean qof_numeric_negative_p | ( | QofNumeric | a | ) |
Returns 1 if a < 0, otherwise returns 0.
Definition at line 137 of file qofnumeric.c.
00138 { 00139 if (qof_numeric_check (a)) 00140 return 0; 00141 else 00142 { 00143 if ((a.num < 0) && (a.denom != 0)) 00144 return 1; 00145 else 00146 return 0; 00147 } 00148 }
static gint64 qof_numeric_num | ( | QofNumeric | a | ) | [inline, static] |
gboolean qof_numeric_positive_p | ( | QofNumeric | a | ) |
Returns 1 if a > 0, otherwise returns 0.
Definition at line 155 of file qofnumeric.c.
00156 { 00157 if (qof_numeric_check (a)) 00158 return 0; 00159 else 00160 { 00161 if ((a.num > 0) && (a.denom != 0)) 00162 return 1; 00163 else 00164 return 0; 00165 } 00166 }
QofNumeric qof_numeric_reduce | ( | QofNumeric | in | ) |
Return input after reducing it by Greated Common Factor (GCF) elimination
Definition at line 888 of file qofnumeric.c.
00889 { 00890 gint64 t; 00891 gint64 num = (in.num < 0) ? (-in.num) : in.num; 00892 gint64 denom = in.denom; 00893 QofNumeric out; 00894 00895 if (qof_numeric_check (in)) 00896 return qof_numeric_error (QOF_ERROR_ARG); 00897 00898 /* The strategy is to use Euclid's algorithm */ 00899 while (denom > 0) 00900 { 00901 t = num % denom; 00902 num = denom; 00903 denom = t; 00904 } 00905 /* num now holds the GCD (Greatest Common Divisor) */ 00906 00907 /* All calculations are done on positive num, since it's not 00908 * well defined what % does for negative values */ 00909 out.num = in.num / num; 00910 out.denom = in.denom / num; 00911 return out; 00912 }
gint qof_numeric_same | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how | |||
) |
Equivalence predicate: Convert both a and b to denom using the specified DENOM and method HOW, and compare numerators the results using QofNumeric_equal.
For example, if a == 7/16 and b == 3/4, QofNumeric_same(a, b, 2, QOF_HOW_RND_TRUNC) == 1 because both 7/16 and 3/4 round to 1/2 under truncation. However, QofNumeric_same(a, b, 2, QOF_HOW_RND_ROUND) == 0 because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds to 2/2.
Definition at line 285 of file qofnumeric.c.
00286 { 00287 QofNumeric aconv, bconv; 00288 00289 aconv = qof_numeric_convert (a, denom, how); 00290 bconv = qof_numeric_convert (b, denom, how); 00291 00292 return (qof_numeric_equal (aconv, bconv)); 00293 }
QofNumeric qof_numeric_sub | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how | |||
) |
Return a-b.
Definition at line 388 of file qofnumeric.c.
00389 { 00390 QofNumeric nb; 00391 00392 if (qof_numeric_check (a) || qof_numeric_check (b)) 00393 return qof_numeric_error (QOF_ERROR_ARG); 00394 00395 nb = b; 00396 nb.num = -nb.num; 00397 return qof_numeric_add (a, nb, denom, how); 00398 }
static QofNumeric qof_numeric_sub_fixed | ( | QofNumeric | a, | |
QofNumeric | b | |||
) | [inline, static] |
Shortcut for most common case: QofNumeric_sub(a, b, QOF_DENOM_AUTO, QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
Definition at line 422 of file qofnumeric.h.
00423 { 00424 return qof_numeric_sub (a, b, QOF_DENOM_AUTO, 00425 QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER); 00426 }
QofNumeric qof_numeric_sub_with_error | ( | QofNumeric | a, | |
QofNumeric | b, | |||
gint64 | denom, | |||
gint | how, | |||
QofNumeric * | error | |||
) |
The same as QofNumeric_sub, but uses error for accumulating conversion roundoff error.
Definition at line 1034 of file qofnumeric.c.
01036 { 01037 QofNumeric diff = qof_numeric_sub (a, b, denom, how); 01038 QofNumeric exact = qof_numeric_sub (a, b, QOF_DENOM_AUTO, 01039 QOF_HOW_DENOM_REDUCE); 01040 QofNumeric err = qof_numeric_sub (diff, exact, QOF_DENOM_AUTO, 01041 QOF_HOW_DENOM_REDUCE); 01042 if (error) 01043 *error = err; 01044 return diff; 01045 }
gdouble qof_numeric_to_double | ( | QofNumeric | in | ) |
Convert numeric to floating-point value.
Definition at line 991 of file qofnumeric.c.
00992 { 00993 if (in.denom > 0) 00994 return (gdouble) in.num / (gdouble) in.denom; 00995 else 00996 return (gdouble) (in.num * -in.denom); 00997 }
gchar* qof_numeric_to_string | ( | QofNumeric | n | ) |
Convert to string. The returned buffer is to be g_free'd by the caller (it was allocated through g_strdup)
Definition at line 1089 of file qofnumeric.c.
01090 { 01091 gchar *result; 01092 gint64 tmpnum = n.num; 01093 gint64 tmpdenom = n.denom; 01094 01095 result = 01096 g_strdup_printf ("%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, 01097 tmpdenom); 01098 01099 return result; 01100 }
static QofNumeric qof_numeric_zero | ( | void | ) | [inline, static] |
create a zero-value QofNumeric
Definition at line 253 of file qofnumeric.h.
00254 { 00255 return qof_numeric_create (0, 1); 00256 }
gboolean qof_numeric_zero_p | ( | QofNumeric | a | ) |
Returns 1 if the given QofNumeric is 0 (zero), else returns 0.
Definition at line 119 of file qofnumeric.c.
00120 { 00121 if (qof_numeric_check (a)) 00122 return 0; 00123 else 00124 { 00125 if ((a.num == 0) && (a.denom != 0)) 00126 return 1; 00127 else 00128 return 0; 00129 } 00130 }