2001-08-07 18:36:04 -05:00
|
|
|
/********************************************************************
|
2004-06-26 21:26:28 -05:00
|
|
|
* gnc-numeric.h - A rational number library *
|
2001-08-07 18:36:04 -05:00
|
|
|
* This program is free software; you can redistribute it and/or *
|
|
|
|
* modify it under the terms of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License*
|
|
|
|
* along with this program; if not, contact: *
|
|
|
|
* *
|
|
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
|
|
|
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02111-1307, USA gnu@gnu.org *
|
|
|
|
* *
|
|
|
|
*******************************************************************/
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** @addtogroup Numeric
|
2005-11-01 21:32:36 -06:00
|
|
|
|
2004-05-06 09:42:00 -05:00
|
|
|
The 'Numeric' functions provide a way of working with rational
|
|
|
|
numbers while maintaining strict control over rounding errors
|
|
|
|
when adding rationals with different denominators. The Numeric
|
|
|
|
class is primarily used for working with monetary amounts,
|
|
|
|
where the denominator typically represents the smallest fraction
|
|
|
|
of the currency (e.g. pennies, centimes). The numeric class
|
|
|
|
can handle any fraction (e.g. twelfth's) and is not limited
|
2004-06-26 22:57:25 -05:00
|
|
|
to fractions that are powers of ten.
|
2004-05-06 09:42:00 -05:00
|
|
|
|
2004-06-26 21:26:28 -05:00
|
|
|
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.
|
2004-05-06 09:42:00 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
EXAMPLE\n
|
|
|
|
-------\n
|
|
|
|
The following program finds the best ::gnc_numeric approximation to
|
|
|
|
the \a math.h constant \a M_PI given a maximum denominator. For
|
|
|
|
large denominators, the ::gnc_numeric approximation is accurate to
|
2004-06-26 21:26:28 -05:00
|
|
|
more decimal places than will generally be needed, but in some cases
|
|
|
|
this may not be good enough. For example,
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
@verbatim
|
2004-06-26 21:26:28 -05:00
|
|
|
M_PI = 3.14159265358979323846
|
|
|
|
245850922 / 78256779 = 3.14159265358979311599 (16 sig figs)
|
|
|
|
3126535 / 995207 = 3.14159265358865047446 (12 sig figs)
|
|
|
|
355 / 113 = 3.14159292035398252096 (7 sig figs)
|
2005-11-01 21:32:36 -06:00
|
|
|
@endverbatim
|
2004-06-26 21:26:28 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
@verbatim
|
2004-06-26 21:26:28 -05:00
|
|
|
#include <glib.h>
|
|
|
|
#include "gnc-numeric.h"
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char ** argv)
|
2004-06-26 22:57:25 -05:00
|
|
|
{
|
2004-06-26 21:26:28 -05:00
|
|
|
gnc_numeric approx, best;
|
|
|
|
double err, best_err=1.0;
|
|
|
|
double m_pi = M_PI;
|
|
|
|
gint64 denom;
|
|
|
|
gint64 max;
|
|
|
|
|
|
|
|
sscanf(argv[1], "%Ld", &max);
|
|
|
|
|
|
|
|
for (denom = 1; denom < max; denom++)
|
2004-06-26 22:57:25 -05:00
|
|
|
{
|
2004-06-26 21:26:28 -05:00
|
|
|
approx = double_to_gnc_numeric (m_pi, denom, GNC_RND_ROUND);
|
|
|
|
err = m_pi - gnc_numeric_to_double (approx);
|
|
|
|
if (fabs (err) < fabs (best_err))
|
2004-06-26 22:57:25 -05:00
|
|
|
{
|
2004-06-26 21:26:28 -05:00
|
|
|
best = approx;
|
|
|
|
best_err = err;
|
|
|
|
printf ("%Ld / %Ld = %.30f\n", gnc_numeric_num (best),
|
|
|
|
gnc_numeric_denom (best), gnc_numeric_to_double (best));
|
2004-06-26 22:57:25 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-11-01 21:32:36 -06:00
|
|
|
@endverbatim
|
|
|
|
|
|
|
|
@{ */
|
|
|
|
/** @file gnc-numeric.h
|
|
|
|
@brief An exact-rational-number library for gnucash.
|
|
|
|
@author Copyright (C) 2000 Bill Gribble
|
|
|
|
@author Copyright (C) 2004 Linas Vepstas <linas@linas.org>
|
|
|
|
*/
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
|
2001-08-07 18:36:04 -05:00
|
|
|
#ifndef GNC_NUMERIC_H
|
|
|
|
#define GNC_NUMERIC_H
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
struct _gnc_numeric
|
|
|
|
{
|
2001-08-07 18:36:04 -05:00
|
|
|
gint64 num;
|
|
|
|
gint64 denom;
|
|
|
|
};
|
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** @brief An rational-number type
|
2003-03-14 17:59:25 -06:00
|
|
|
*
|
2004-06-26 22:57:25 -05:00
|
|
|
* This is a rational number, defined by numerator and denominator. */
|
2001-08-07 18:36:04 -05:00
|
|
|
typedef struct _gnc_numeric gnc_numeric;
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Arguments Standard Arguments to most functions
|
2004-06-26 22:57:25 -05:00
|
|
|
|
|
|
|
Most of the gnc_numeric arithmetic functions take two arguments
|
2004-06-27 00:02:12 -05:00
|
|
|
in addition to their numeric args: 'denom', which is the denominator
|
|
|
|
to use in the output gnc_numeric object, and 'how'. which
|
2004-06-26 22:57:25 -05:00
|
|
|
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.
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
Valid values for denom are:
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_DENOM_AUTO -- compute denominator exactly
|
2005-11-01 21:32:36 -06:00
|
|
|
integer n -- Force the denominator of the result to be this integer
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_DENOM_RECIPROCAL -- Use 1/n as the denominator (???huh???)
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
Valid values for 'how' are bitwise combinations of zero or one
|
2004-06-26 22:57:25 -05:00
|
|
|
"rounding instructions" with zero or one "denominator types".
|
|
|
|
Valid rounding instructions are:
|
|
|
|
GNC_HOW_RND_FLOOR
|
|
|
|
GNC_HOW_RND_CEIL
|
|
|
|
GNC_HOW_RND_TRUNC
|
|
|
|
GNC_HOW_RND_PROMOTE
|
|
|
|
GNC_HOW_RND_ROUND_HALF_DOWN
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP
|
|
|
|
GNC_HOW_RND_ROUND
|
|
|
|
GNC_HOW_RND_NEVER
|
|
|
|
|
|
|
|
The denominator type specifies how to compute a denominator if
|
2004-06-27 00:02:12 -05:00
|
|
|
GNC_DENOM_AUTO is specified as the 'denom'. Valid
|
2004-06-26 22:57:25 -05:00
|
|
|
denominator types are:
|
|
|
|
GNC_HOW_DENOM_EXACT
|
|
|
|
GNC_HOW_DENOM_REDUCE
|
|
|
|
GNC_HOW_DENOM_LCD
|
|
|
|
GNC_HOW_DENOM_FIXED
|
|
|
|
GNC_HOW_DENOM_SIGFIGS(N)
|
|
|
|
|
|
|
|
To use traditional rational-number operational semantics (all results
|
|
|
|
are exact and are reduced to relatively-prime fractions) pass the
|
2004-06-27 00:02:12 -05:00
|
|
|
argument GNC_DENOM_AUTO as 'denom' and
|
|
|
|
GNC_HOW_DENOM_REDUCE| GNC_HOW_RND_NEVER as 'how'.
|
2004-06-26 22:57:25 -05:00
|
|
|
|
|
|
|
To enforce strict financial semantics (such that all operands must have
|
|
|
|
the same denominator as each other and as the result), use
|
2004-06-27 00:02:12 -05:00
|
|
|
GNC_DENOM_AUTO as 'denom' and
|
|
|
|
GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER as 'how'.
|
2005-11-01 21:32:36 -06:00
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** \brief bitmasks for HOW flags.
|
2004-06-26 22:57:25 -05:00
|
|
|
|
2004-05-29 17:43:49 -05:00
|
|
|
* bits 8-15 of 'how' are reserved for the number of significant
|
2004-06-26 22:57:25 -05:00
|
|
|
* digits to use in the output with GNC_HOW_DENOM_SIGFIG
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
#define GNC_NUMERIC_RND_MASK 0x0000000f
|
|
|
|
#define GNC_NUMERIC_DENOM_MASK 0x000000f0
|
|
|
|
#define GNC_NUMERIC_SIGFIGS_MASK 0x0000ff00
|
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** \brief Rounding/Truncation modes for operations.
|
|
|
|
|
2004-06-26 21:26:28 -05:00
|
|
|
* 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:
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
enum {
|
2004-06-26 21:26:28 -05:00
|
|
|
/** Round toward -infinity */
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_FLOOR = 0x01,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Round toward +infinity */
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_CEIL = 0x02,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Truncate fractions (round toward zero) */
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_TRUNC = 0x03,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Promote fractions (round away from zero) */
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_PROMOTE = 0x04,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Round to the nearest integer, rounding toward zero
|
|
|
|
* when there are two equidistant nearest integers.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_ROUND_HALF_DOWN = 0x05,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Round to the nearest integer, rounding away from zero
|
|
|
|
* when there are two equidistant nearest integers.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_ROUND_HALF_UP = 0x06,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Use unbiased ("banker's") rounding. This rounds to the
|
|
|
|
* nearest integer, and to the nearest even integer when there
|
|
|
|
* are two equidistant nearest integers. This is generally the
|
|
|
|
* one you should use for financial quantities.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_ROUND = 0x07,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Never round at all, and signal an error if there is a
|
|
|
|
* fractional result in a computation.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_RND_NEVER = 0x08
|
2001-08-07 18:36:04 -05:00
|
|
|
};
|
|
|
|
|
2004-06-26 21:26:28 -05:00
|
|
|
/** How to compute a denominator, or'ed into the "how" field. */
|
2001-08-07 18:36:04 -05:00
|
|
|
enum {
|
2004-06-26 21:26:28 -05:00
|
|
|
/** Use any denominator which gives an exactly correct ratio of
|
|
|
|
* numerator to denominator. Use EXACT when you do not wish to
|
|
|
|
* lose any information in the result but also do not want to
|
|
|
|
* spend any time finding the "best" denominator.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_EXACT = 0x10,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Reduce the result value by common factor elimination,
|
|
|
|
* using the smallest possible value for the denominator that
|
|
|
|
* keeps the correct ratio. The numerator and denominator of
|
|
|
|
* the result are relatively prime.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_REDUCE = 0x20,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Find the least common multiple of the arguments' denominators
|
|
|
|
* and use that as the denominator of the result.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_LCD = 0x30,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** All arguments are required to have the same denominator,
|
|
|
|
* that denominator is to be used in the output, and an error
|
|
|
|
* is to be signaled if any argument has a different denominator.
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_FIXED = 0x40,
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Round to the number of significant figures given in the rounding
|
2004-06-26 22:57:25 -05:00
|
|
|
* instructions by the GNC_HOW_DENOM_SIGFIGS () macro.
|
2004-06-26 21:26:28 -05:00
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_SIGFIG = 0x50
|
2001-08-07 18:36:04 -05:00
|
|
|
};
|
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Build a 'how' value that will generate a denominator that will
|
|
|
|
* keep at least n significant figures in the result.
|
|
|
|
*/
|
|
|
|
#define GNC_HOW_DENOM_SIGFIGS( n ) ( ((( n ) & 0xff) << 8) | GNC_HOW_DENOM_SIGFIG)
|
|
|
|
#define GNC_HOW_GET_SIGFIGS( a ) ( (( a ) & 0xff00 ) >> 8)
|
|
|
|
|
2004-05-29 17:43:49 -05:00
|
|
|
/** Error codes */
|
|
|
|
typedef enum {
|
|
|
|
GNC_ERROR_OK = 0, /**< No error */
|
|
|
|
GNC_ERROR_ARG = -1, /**< Argument is not a valid number */
|
|
|
|
GNC_ERROR_OVERFLOW = -2, /**< Intermediate result overflow */
|
2004-06-26 21:26:28 -05:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** GNC_HOW_DENOM_FIXED was specified, but argument denominators differed. */
|
2004-06-26 21:26:28 -05:00
|
|
|
GNC_ERROR_DENOM_DIFF = -3,
|
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** GNC_HOW_RND_NEVER was specified, but the result could not be
|
2004-06-26 21:26:28 -05:00
|
|
|
* converted to the desired denominator without a remainder. */
|
|
|
|
GNC_ERROR_REMAINDER = -4
|
2004-05-29 17:43:49 -05:00
|
|
|
} GNCNumericErrorCode;
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Values that can be passed as the 'denom' argument.
|
|
|
|
* The include a positive number n to be used as the
|
2005-11-01 21:32:36 -06:00
|
|
|
* denominator of the output value. Other possibilities
|
2004-06-26 21:26:28 -05:00
|
|
|
* include the list below:
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** Compute an appropriate denominator automatically. Flags in
|
2004-06-27 00:02:12 -05:00
|
|
|
* the 'how' argument will specify how to compute the denominator.
|
2004-06-26 21:26:28 -05:00
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
#define GNC_DENOM_AUTO 0
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** Use the value 1/n as the denominator of the output value. */
|
2001-08-07 18:36:04 -05:00
|
|
|
#define GNC_DENOM_RECIPROCAL( a ) (- ( a ))
|
2004-06-26 21:26:28 -05:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Constructors
|
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Make a gnc_numeric from numerator and denominator */
|
|
|
|
static inline
|
|
|
|
gnc_numeric gnc_numeric_create(gint64 num, gint64 denom) {
|
|
|
|
gnc_numeric out;
|
|
|
|
out.num = num;
|
|
|
|
out.denom = denom;
|
|
|
|
return out;
|
|
|
|
}
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2003-03-14 17:59:25 -06:00
|
|
|
/** create a zero-value gnc_numeric */
|
2004-06-26 22:57:25 -05:00
|
|
|
static inline
|
|
|
|
gnc_numeric gnc_numeric_zero(void) { return gnc_numeric_create(0, 1); }
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Convert a floating-point number to a gnc_numeric.
|
2004-06-27 00:02:12 -05:00
|
|
|
* Both 'denom' and 'how' are used as in arithmetic,
|
|
|
|
* but GNC_DENOM_AUTO is not recognized; a denominator
|
2004-06-26 22:57:25 -05:00
|
|
|
* must be specified either explicitctly or through sigfigs.
|
|
|
|
*/
|
2003-03-26 17:07:01 -06:00
|
|
|
gnc_numeric double_to_gnc_numeric(double in, gint64 denom,
|
|
|
|
gint how);
|
|
|
|
|
2004-10-31 19:37:10 -06:00
|
|
|
/** Read a gnc_numeric from str, skipping any leading whitespace.
|
|
|
|
* Return TRUE on success and store the resulting value in "n".
|
2004-06-26 22:57:25 -05:00
|
|
|
* Return NULL on error. */
|
2004-10-31 19:37:10 -06:00
|
|
|
gboolean string_to_gnc_numeric(const gchar* str, gnc_numeric *n);
|
2003-03-26 17:07:01 -06:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Create a gnc_numeric object that signals the error condition
|
2004-06-27 00:02:12 -05:00
|
|
|
* noted by error_code, rather than a number.
|
2004-06-26 22:57:25 -05:00
|
|
|
*/
|
2004-05-29 17:43:49 -05:00
|
|
|
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code);
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Value Accessors
|
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Return numerator */
|
|
|
|
static inline
|
|
|
|
gint64 gnc_numeric_num(gnc_numeric a) { return a.num; }
|
|
|
|
/** Return denominator */
|
|
|
|
static inline
|
|
|
|
gint64 gnc_numeric_denom(gnc_numeric a) { return a.denom; }
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Convert numeric to floating-point value. */
|
2003-03-26 17:07:01 -06:00
|
|
|
double gnc_numeric_to_double(gnc_numeric in);
|
|
|
|
|
|
|
|
/** Convert to string. The returned buffer is to be g_free'd by the
|
2004-06-26 22:57:25 -05:00
|
|
|
* caller (it was allocated through g_strdup) */
|
2003-03-26 17:07:01 -06:00
|
|
|
gchar *gnc_numeric_to_string(gnc_numeric n);
|
2004-07-04 12:26:50 -05:00
|
|
|
|
|
|
|
/** Convert to string. Uses a static, non-thread-safe buffer.
|
|
|
|
* For internal use only. */
|
|
|
|
gchar * gnc_num_dbg_to_string(gnc_numeric n);
|
2004-06-27 00:02:12 -05:00
|
|
|
/** @}*/
|
2003-03-26 17:07:01 -06:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Comparisons and Predicates
|
|
|
|
@{
|
|
|
|
*/
|
2003-03-26 17:07:01 -06:00
|
|
|
/** Check for error signal in value. Returns GNC_ERROR_OK (==0) if
|
2004-05-29 17:43:49 -05:00
|
|
|
* the number appears to be valid, otherwise it returns the
|
2004-06-26 21:26:28 -05:00
|
|
|
* type of error. Error values always have a denominator of zero.
|
2004-05-29 17:43:49 -05:00
|
|
|
*/
|
|
|
|
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a);
|
2003-03-26 17:07:01 -06:00
|
|
|
|
|
|
|
/** Returns 1 if a>b, -1 if b>a, 0 if a == b */
|
2001-08-07 18:36:04 -05:00
|
|
|
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b);
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** Returns 1 if the given gnc_numeric is 0 (zero), else returns 0. */
|
|
|
|
gboolean gnc_numeric_zero_p(gnc_numeric a);
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** Returns 1 if a < 0, otherwise returns 0. */
|
2004-06-26 21:26:28 -05:00
|
|
|
gboolean gnc_numeric_negative_p(gnc_numeric a);
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** Returns 1 if a > 0, otherwise returns 0. */
|
2004-06-26 21:26:28 -05:00
|
|
|
gboolean gnc_numeric_positive_p(gnc_numeric a);
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Equivalence predicate: Returns TRUE (1) if a and b are
|
|
|
|
* exactly the same (have the same numerator and denominator)
|
2001-08-07 18:36:04 -05:00
|
|
|
*/
|
2004-06-25 19:18:17 -05:00
|
|
|
gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b);
|
2003-03-30 00:29:19 -06:00
|
|
|
|
2003-03-26 17:07:01 -06:00
|
|
|
/** Equivalence predicate: Returns TRUE (1) if a and b represent
|
2004-06-26 22:57:25 -05:00
|
|
|
* the same number. That is, return TRUE if the ratios, when
|
|
|
|
* reduced by eliminating common factors, are identical.
|
2003-03-26 17:07:01 -06:00
|
|
|
*/
|
2004-06-25 19:18:17 -05:00
|
|
|
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b);
|
2003-03-30 00:29:19 -06:00
|
|
|
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Equivalence predicate:
|
2004-06-27 00:02:12 -05:00
|
|
|
* Convert both a and b to denom using the
|
2004-06-26 22:57:25 -05:00
|
|
|
* specified DENOM and method HOW, and compare numerators
|
|
|
|
* the results using gnc_numeric_equal.
|
|
|
|
*
|
2004-06-27 00:02:12 -05:00
|
|
|
For example, if a == 7/16 and b == 3/4,
|
|
|
|
gnc_numeric_same(a, b, 2, GNC_HOW_RND_TRUNC) == 1
|
2004-06-26 22:57:25 -05:00
|
|
|
because both 7/16 and 3/4 round to 1/2 under truncation. However,
|
2004-06-27 00:02:12 -05:00
|
|
|
gnc_numeric_same(a, b, 2, GNC_HOW_RND_ROUND) == 0
|
2004-06-26 22:57:25 -05:00
|
|
|
because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
|
|
|
|
to 2/2.
|
2003-03-26 17:07:01 -06:00
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
int gnc_numeric_same(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how);
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Arithmetic Operations
|
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Return a+b. */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how);
|
2004-06-26 22:57:25 -05:00
|
|
|
|
|
|
|
/** Return a-b. */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how);
|
2004-06-26 21:26:28 -05:00
|
|
|
|
|
|
|
/** 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.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how);
|
2004-06-26 18:40:01 -05:00
|
|
|
|
|
|
|
/** 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.
|
|
|
|
*/
|
|
|
|
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y,
|
2001-08-07 18:36:04 -05:00
|
|
|
gint64 denom, gint how);
|
2003-03-26 17:07:01 -06:00
|
|
|
/** Negate the argument */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_neg(gnc_numeric a);
|
2004-06-26 21:26:28 -05:00
|
|
|
|
2003-03-26 17:07:01 -06:00
|
|
|
/** Return the absolute value of the argument */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_abs(gnc_numeric a);
|
|
|
|
|
2003-03-30 21:25:37 -06:00
|
|
|
/**
|
2004-06-26 21:26:28 -05:00
|
|
|
* Shortcut for common case: gnc_numeric_add(a, b, GNC_DENOM_AUTO,
|
2004-06-26 22:57:25 -05:00
|
|
|
* GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
|
2003-03-30 21:25:37 -06:00
|
|
|
*/
|
2004-06-26 21:26:28 -05:00
|
|
|
static inline
|
|
|
|
gnc_numeric gnc_numeric_add_fixed(gnc_numeric a, gnc_numeric b) {
|
|
|
|
return gnc_numeric_add(a, b, GNC_DENOM_AUTO,
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
|
2004-06-26 21:26:28 -05:00
|
|
|
}
|
|
|
|
|
2003-03-30 21:25:37 -06:00
|
|
|
/**
|
|
|
|
* Shortcut for most common case: gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
|
2004-06-26 22:57:25 -05:00
|
|
|
* GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
|
2003-03-30 21:25:37 -06:00
|
|
|
*/
|
2004-06-26 21:26:28 -05:00
|
|
|
static inline
|
|
|
|
gnc_numeric gnc_numeric_sub_fixed(gnc_numeric a, gnc_numeric b) {
|
|
|
|
return gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
|
2004-06-26 22:57:25 -05:00
|
|
|
GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
|
2004-06-26 21:26:28 -05:00
|
|
|
}
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Arithmetic Functions with Exact Error Returns
|
|
|
|
@{
|
|
|
|
*/
|
2004-06-27 00:02:12 -05:00
|
|
|
/** The same as gnc_numeric_add, but uses 'error' for accumulating
|
2004-06-26 22:57:25 -05:00
|
|
|
* conversion roundoff error. */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_add_with_error(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how,
|
|
|
|
gnc_numeric * error);
|
2004-06-26 22:57:25 -05:00
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** The same as gnc_numeric_sub, but uses error for accumulating
|
2004-06-26 22:57:25 -05:00
|
|
|
* conversion roundoff error. */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_sub_with_error(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how,
|
|
|
|
gnc_numeric * error);
|
2004-06-26 21:26:28 -05:00
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** The same as gnc_numeric_mul, but uses error for
|
2004-06-26 21:26:28 -05:00
|
|
|
* accumulating conversion roundoff error.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_mul_with_error(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how,
|
|
|
|
gnc_numeric * error);
|
2004-06-26 22:57:25 -05:00
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** The same as gnc_numeric_div, but uses error for
|
2004-06-26 22:57:25 -05:00
|
|
|
* accumulating conversion roundoff error.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_div_with_error(gnc_numeric a, gnc_numeric b,
|
|
|
|
gint64 denom, gint how,
|
|
|
|
gnc_numeric * error);
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @name Change Denominator
|
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
/** Change the denominator of a gnc_numeric value to the
|
|
|
|
* specified denominator under standard arguments
|
2004-06-27 00:02:12 -05:00
|
|
|
* 'denom' and 'how'.
|
2004-06-26 22:57:25 -05:00
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_convert(gnc_numeric in, gint64 denom,
|
|
|
|
gint how);
|
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** Same as gnc_numeric_convert, but return a remainder
|
2004-06-26 22:57:25 -05:00
|
|
|
* value for accumulating conversion error.
|
|
|
|
*/
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_convert_with_error(gnc_numeric in, gint64 denom,
|
|
|
|
gint how,
|
|
|
|
gnc_numeric * error);
|
|
|
|
|
2004-06-26 21:26:28 -05:00
|
|
|
/** Return input after reducing it by Greated Common Factor (GCF)
|
|
|
|
* elimination */
|
2001-08-07 18:36:04 -05:00
|
|
|
gnc_numeric gnc_numeric_reduce(gnc_numeric in);
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
|
2004-06-27 00:02:12 -05:00
|
|
|
/** @name Deprecated, backwards-compatible definitions
|
2005-11-01 21:32:36 -06:00
|
|
|
@{
|
|
|
|
*/
|
2004-06-26 22:57:25 -05:00
|
|
|
#define GNC_RND_FLOOR GNC_HOW_RND_FLOOR
|
|
|
|
#define GNC_RND_CEIL GNC_HOW_RND_CEIL
|
|
|
|
#define GNC_RND_TRUNC GNC_HOW_RND_TRUNC
|
|
|
|
#define GNC_RND_PROMOTE GNC_HOW_RND_PROMOTE
|
|
|
|
#define GNC_RND_ROUND_HALF_DOWN GNC_HOW_RND_ROUND_HALF_DOWN
|
|
|
|
#define GNC_RND_ROUND_HALF_UP GNC_HOW_RND_ROUND_HALF_UP
|
|
|
|
#define GNC_RND_ROUND GNC_HOW_RND_ROUND
|
|
|
|
#define GNC_RND_NEVER GNC_HOW_RND_NEVER
|
|
|
|
|
|
|
|
#define GNC_DENOM_EXACT GNC_HOW_DENOM_EXACT
|
|
|
|
#define GNC_DENOM_REDUCE GNC_HOW_DENOM_REDUCE
|
|
|
|
#define GNC_DENOM_LCD GNC_HOW_DENOM_LCD
|
|
|
|
#define GNC_DENOM_FIXED GNC_HOW_DENOM_FIXED
|
|
|
|
#define GNC_DENOM_SIGFIG GNC_HOW_DENOM_SIGFIG
|
|
|
|
|
|
|
|
#define GNC_DENOM_SIGFIGS(X) GNC_HOW_DENOM_SIGFIGS(X)
|
|
|
|
#define GNC_NUMERIC_GET_SIGFIGS(X) GNC_HOW_GET_SIGFIGS(X)
|
2005-11-01 21:32:36 -06:00
|
|
|
/** @} */
|
|
|
|
/** @} */
|
2001-08-07 18:36:04 -05:00
|
|
|
#endif
|