Branch data Line data Source code
1 : : /********************************************************************
2 : : * gnc-numeric.h - A rational number library *
3 : : * This program is free software; you can redistribute it and/or *
4 : : * modify it under the terms of the GNU General Public License as *
5 : : * published by the Free Software Foundation; either version 2 of *
6 : : * the License, or (at your option) any later version. *
7 : : * *
8 : : * This program is distributed in the hope that it will be useful, *
9 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 : : * GNU General Public License for more details. *
12 : : * *
13 : : * You should have received a copy of the GNU General Public License*
14 : : * along with this program; if not, contact: *
15 : : * *
16 : : * Free Software Foundation Voice: +1-617-542-5942 *
17 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
18 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
19 : : * *
20 : : *******************************************************************/
21 : :
22 : : /** @addtogroup Numeric
23 : :
24 : : The 'Numeric' functions provide a way of working with rational
25 : : numbers while maintaining strict control over rounding errors
26 : : when adding rationals with different denominators. The Numeric
27 : : class is primarily used for working with monetary amounts,
28 : : where the denominator typically represents the smallest fraction
29 : : of the currency (e.g. pennies, centimes). The numeric class
30 : : can handle any fraction (e.g. twelfth's) and is not limited
31 : : to fractions that are powers of ten.
32 : :
33 : : A 'Numeric' value represents a number in rational form, with a
34 : : 64-bit integer as numerator and denominator. Rationals are
35 : : ideal for many uses, such as performing exact, roundoff-error-free
36 : : addition and multiplication, but 64-bit rationals do not have
37 : : the dynamic range of floating point numbers.
38 : :
39 : : @{ */
40 : : /** @file gnc-numeric.h
41 : : @brief An exact-rational-number library for gnucash.
42 : : (to be renamed qofnumeric.h in libqof2)
43 : : @author Copyright (C) 2000 Bill Gribble
44 : : @author Copyright (C) 2004 Linas Vepstas <linas@linas.org>
45 : : */
46 : :
47 : :
48 : : #ifndef GNC_NUMERIC_H
49 : : #define GNC_NUMERIC_H
50 : :
51 : : #include <glib-object.h>
52 : :
53 : : #ifdef __cplusplus
54 : : extern "C"
55 : : {
56 : : #endif
57 : :
58 : : struct _gnc_numeric
59 : : {
60 : : gint64 num;
61 : : gint64 denom;
62 : : };
63 : :
64 : : /** @brief An rational-number type
65 : : *
66 : : * This is a rational number, defined by numerator and denominator. */
67 : : typedef struct _gnc_numeric gnc_numeric;
68 : :
69 : : /** @name Arguments Standard Arguments to most functions
70 : :
71 : : Most of the gnc_numeric arithmetic functions take two arguments
72 : : in addition to their numeric args: 'denom', which is the denominator
73 : : to use in the output gnc_numeric object, and 'how'. which
74 : : describes how the arithmetic result is to be converted to that
75 : : denominator. This combination of output denominator and rounding policy
76 : : allows the results of financial and other rational computations to be
77 : : properly rounded to the appropriate units.
78 : :
79 : : Watch out: You \e must specify a rounding policy such as
80 : : GNC_HOW_RND_NEVER, otherwise the fractional part of the input
81 : : value might silently get discarded!
82 : :
83 : : Valid values for denom are:
84 : : GNC_DENOM_AUTO -- compute denominator exactly
85 : : integer n -- Force the denominator of the result to be this integer
86 : : GNC_DENOM_RECIPROCAL -- Use 1/n as the denominator (???huh???)
87 : :
88 : : Valid values for 'how' are bitwise combinations of zero or one
89 : : "rounding instructions" with zero or one "denominator types".
90 : : Valid rounding instructions are:
91 : : GNC_HOW_RND_FLOOR
92 : : GNC_HOW_RND_CEIL
93 : : GNC_HOW_RND_TRUNC
94 : : GNC_HOW_RND_PROMOTE
95 : : GNC_HOW_RND_ROUND_HALF_DOWN
96 : : GNC_HOW_RND_ROUND_HALF_UP
97 : : GNC_HOW_RND_ROUND
98 : : GNC_HOW_RND_NEVER
99 : :
100 : : The denominator type specifies how to compute a denominator if
101 : : GNC_DENOM_AUTO is specified as the 'denom'. Valid
102 : : denominator types are:
103 : : GNC_HOW_DENOM_EXACT
104 : : GNC_HOW_DENOM_REDUCE
105 : : GNC_HOW_DENOM_LCD
106 : : GNC_HOW_DENOM_FIXED
107 : : GNC_HOW_DENOM_SIGFIGS(N)
108 : :
109 : : To use traditional rational-number operational semantics (all results
110 : : are exact and are reduced to relatively-prime fractions) pass the
111 : : argument GNC_DENOM_AUTO as 'denom' and
112 : : GNC_HOW_DENOM_REDUCE| GNC_HOW_RND_NEVER as 'how'.
113 : :
114 : : To enforce strict financial semantics (such that all operands must have
115 : : the same denominator as each other and as the result), use
116 : : GNC_DENOM_AUTO as 'denom' and
117 : : GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER as 'how'.
118 : : @{
119 : : */
120 : :
121 : : /** \brief bitmasks for HOW flags.
122 : :
123 : : * bits 8-15 of 'how' are reserved for the number of significant
124 : : * digits to use in the output with GNC_HOW_DENOM_SIGFIG
125 : : */
126 : : #define GNC_NUMERIC_RND_MASK 0x0000000f
127 : : #define GNC_NUMERIC_DENOM_MASK 0x000000f0
128 : : #define GNC_NUMERIC_SIGFIGS_MASK 0x0000ff00
129 : :
130 : : /** \brief Rounding/Truncation modes for operations.
131 : :
132 : : * Rounding instructions control how fractional parts in the specified
133 : : * denominator affect the result. For example, if a computed result is
134 : : * "3/4" but the specified denominator for the return value is 2, should
135 : : * the return value be "1/2" or "2/2"?
136 : : *
137 : : * Watch out: You \e must specify a rounding policy such as
138 : : * GNC_HOW_RND_NEVER, otherwise the fractional part of the input value
139 : : * might silently get discarded!
140 : : *
141 : : * Possible rounding instructions are:
142 : : */
143 : : enum
144 : : {
145 : : /** Round toward -infinity */
146 : : GNC_HOW_RND_FLOOR = 0x01,
147 : :
148 : : /** Round toward +infinity */
149 : : GNC_HOW_RND_CEIL = 0x02,
150 : :
151 : : /** Truncate fractions (round toward zero) */
152 : : GNC_HOW_RND_TRUNC = 0x03,
153 : :
154 : : /** Promote fractions (round away from zero) */
155 : : GNC_HOW_RND_PROMOTE = 0x04,
156 : :
157 : : /** Round to the nearest integer, rounding toward zero
158 : : * when there are two equidistant nearest integers.
159 : : */
160 : : GNC_HOW_RND_ROUND_HALF_DOWN = 0x05,
161 : :
162 : : /** Round to the nearest integer, rounding away from zero
163 : : * when there are two equidistant nearest integers.
164 : : */
165 : : GNC_HOW_RND_ROUND_HALF_UP = 0x06,
166 : :
167 : : /** Use unbiased ("banker's") rounding. This rounds to the
168 : : * nearest integer, and to the nearest even integer when there
169 : : * are two equidistant nearest integers. This is generally the
170 : : * one you should use for financial quantities.
171 : : */
172 : : GNC_HOW_RND_ROUND = 0x07,
173 : :
174 : : /** Never round at all, and signal an error if there is a
175 : : * fractional result in a computation.
176 : : */
177 : : GNC_HOW_RND_NEVER = 0x08
178 : : };
179 : :
180 : : /** How to compute a denominator, or'ed into the "how" field. */
181 : : enum
182 : : {
183 : : /** Use any denominator which gives an exactly correct ratio of
184 : : * numerator to denominator. Use EXACT when you do not wish to
185 : : * lose any information in the result but also do not want to
186 : : * spend any time finding the "best" denominator.
187 : : */
188 : : GNC_HOW_DENOM_EXACT = 0x10,
189 : :
190 : : /** Reduce the result value by common factor elimination,
191 : : * using the smallest possible value for the denominator that
192 : : * keeps the correct ratio. The numerator and denominator of
193 : : * the result are relatively prime.
194 : : */
195 : : GNC_HOW_DENOM_REDUCE = 0x20,
196 : :
197 : : /** Find the least common multiple of the arguments' denominators
198 : : * and use that as the denominator of the result.
199 : : */
200 : : GNC_HOW_DENOM_LCD = 0x30,
201 : :
202 : : /** All arguments are required to have the same denominator,
203 : : * that denominator is to be used in the output, and an error
204 : : * is to be signaled if any argument has a different denominator.
205 : : */
206 : : GNC_HOW_DENOM_FIXED = 0x40,
207 : :
208 : : /** Round to the number of significant figures given in the rounding
209 : : * instructions by the GNC_HOW_DENOM_SIGFIGS () macro.
210 : : */
211 : : GNC_HOW_DENOM_SIGFIG = 0x50
212 : : };
213 : :
214 : : /** Build a 'how' value that will generate a denominator that will
215 : : * keep at least n significant figures in the result.
216 : : */
217 : : #define GNC_HOW_DENOM_SIGFIGS( n ) ( ((( n ) & 0xff) << 8) | GNC_HOW_DENOM_SIGFIG)
218 : : #define GNC_HOW_GET_SIGFIGS( a ) ( (( a ) & 0xff00 ) >> 8)
219 : :
220 : : /** Error codes */
221 : : typedef enum
222 : : {
223 : : GNC_ERROR_OK = 0, /**< No error */
224 : : GNC_ERROR_ARG = -1, /**< Argument is not a valid number */
225 : : GNC_ERROR_OVERFLOW = -2, /**< Intermediate result overflow */
226 : :
227 : : /** GNC_HOW_DENOM_FIXED was specified, but argument denominators differed. */
228 : : GNC_ERROR_DENOM_DIFF = -3,
229 : :
230 : : /** GNC_HOW_RND_NEVER was specified, but the result could not be
231 : : * converted to the desired denominator without a remainder. */
232 : : GNC_ERROR_REMAINDER = -4
233 : : } GNCNumericErrorCode;
234 : :
235 : :
236 : : /** Values that can be passed as the 'denom' argument.
237 : : * The include a positive number n to be used as the
238 : : * denominator of the output value. Other possibilities
239 : : * include the list below:
240 : : */
241 : :
242 : : /** Compute an appropriate denominator automatically. Flags in
243 : : * the 'how' argument will specify how to compute the denominator.
244 : : */
245 : : #define GNC_DENOM_AUTO 0
246 : :
247 : : /** @} */
248 : :
249 : : /** @name Constructors
250 : : @{
251 : : */
252 : : /** Returns a newly created gnc_numeric with the given numerator and
253 : : * denominator, that is "num/denom". */
254 : : static inline
255 : 271832 : gnc_numeric gnc_numeric_create(gint64 num, gint64 denom)
256 : : {
257 : : gnc_numeric out;
258 : 271832 : out.num = num;
259 : 271832 : out.denom = denom;
260 : 271832 : return out;
261 : : }
262 : :
263 : : /** Returns a newly created gnc_numeric of value zero, that is "0/1". */
264 : : static inline
265 : 143781 : gnc_numeric gnc_numeric_zero(void)
266 : : {
267 : 143781 : return gnc_numeric_create(0, 1);
268 : : }
269 : :
270 : : /** Convert a floating-point number to a gnc_numeric.
271 : : *
272 : : * Both 'denom' and 'how' are used as in arithmetic.
273 : : *
274 : : * \sa \ref Arguments
275 : : *
276 : : * \param n The double value that is converted into a gnc_numeric
277 : : *
278 : : * \param denom The denominator of the gnc_numeric return value. If
279 : : * the 'how' argument contains the GNC_HOW_DENOM_SIGFIG flag, this
280 : : * value will be ignored. If GNC_DENOM_AUTO is given an appropriate
281 : : * power of ten will be used for the denominator (it may be reduced
282 : : * by rounding if appropriate).
283 : : *
284 : : * \param how Describes the rounding policy and output
285 : : * denominator. Watch out: You must specify a rounding policy such
286 : : * as GNC_HOW_RND_NEVER, otherwise the fractional part of the input
287 : : * value is silently discarded! Common values for 'how' are
288 : : * (GNC_HOW_DENOM_REDUCE|GNC_HOW_RND_NEVER) or
289 : : * (GNC_HOW_DENOM_FIXED|GNC_HOW_RND_NEVER).
290 : : *
291 : : * \return The newly created gnc_numeric rational value.
292 : : */
293 : : gnc_numeric double_to_gnc_numeric(double n, gint64 denom,
294 : : gint how);
295 : :
296 : : /** Read a gnc_numeric from str, skipping any leading whitespace.
297 : : * Returns the resulting gnc_numeric.
298 : : * Return GNC_ERROR_ARG on error. */
299 : : gnc_numeric gnc_numeric_from_string (const gchar* str);
300 : : /** Create a gnc_numeric object that signals the error condition
301 : : * noted by error_code, rather than a number.
302 : : */
303 : : gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code);
304 : :
305 : : /** Returns a string representation of the given GNCNumericErrorCode.
306 : : */
307 : : const char* gnc_numeric_errorCode_to_string(GNCNumericErrorCode error_code);
308 : : /** @} */
309 : :
310 : : /** @name Value Accessors
311 : : @{
312 : : */
313 : : /** Returns the numerator of the given gnc_numeric value. */
314 : : static inline
315 : 10293 : gint64 gnc_numeric_num(gnc_numeric a)
316 : : {
317 : 10293 : return a.num;
318 : : }
319 : : /** Returns the denominator of the given gnc_numeric value. */
320 : : static inline
321 : 10323 : gint64 gnc_numeric_denom(gnc_numeric a)
322 : : {
323 : 10323 : return a.denom;
324 : : }
325 : :
326 : : /** Convert numeric to floating-point value. */
327 : : gdouble gnc_numeric_to_double(gnc_numeric n);
328 : :
329 : : /** Convert to string. The returned buffer is to be g_free'd by the
330 : : * caller (it was allocated through g_strdup) */
331 : : gchar *gnc_numeric_to_string(gnc_numeric n);
332 : :
333 : : /** Convert to string. Uses a static, non-thread-safe buffer.
334 : : * For internal use only. */
335 : : gchar * gnc_num_dbg_to_string(gnc_numeric n);
336 : : /** @}*/
337 : :
338 : : /** @name Comparisons and Predicates
339 : : @{
340 : : */
341 : : /** Check for error signal in value. Returns GNC_ERROR_OK (==0) if
342 : : * the number appears to be valid, otherwise it returns the
343 : : * type of error. Error values always have a denominator of zero.
344 : : */
345 : : GNCNumericErrorCode gnc_numeric_check(gnc_numeric a);
346 : :
347 : : /** Returns 1 if a>b, -1 if b>a, 0 if a == b */
348 : : gint gnc_numeric_compare(gnc_numeric a, gnc_numeric b);
349 : :
350 : : /** Returns 1 if the given gnc_numeric is 0 (zero), else returns 0. */
351 : : gboolean gnc_numeric_zero_p(gnc_numeric a);
352 : :
353 : : /** Returns 1 if a < 0, otherwise returns 0. */
354 : : gboolean gnc_numeric_negative_p(gnc_numeric a);
355 : :
356 : : /** Returns 1 if a > 0, otherwise returns 0. */
357 : : gboolean gnc_numeric_positive_p(gnc_numeric a);
358 : :
359 : : /** Equivalence predicate: Returns TRUE (1) if a and b are
360 : : * exactly the same (have the same numerator and denominator)
361 : : */
362 : : gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b);
363 : :
364 : : /** Equivalence predicate: Returns TRUE (1) if a and b represent
365 : : * the same number. That is, return TRUE if the ratios, when
366 : : * reduced by eliminating common factors, are identical.
367 : : */
368 : : gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b);
369 : :
370 : : /** Equivalence predicate:
371 : : * Convert both a and b to denom using the
372 : : * specified DENOM and method HOW, and compare numerators
373 : : * the results using gnc_numeric_equal.
374 : : *
375 : : For example, if a == 7/16 and b == 3/4,
376 : : gnc_numeric_same(a, b, 2, GNC_HOW_RND_TRUNC) == 1
377 : : because both 7/16 and 3/4 round to 1/2 under truncation. However,
378 : : gnc_numeric_same(a, b, 2, GNC_HOW_RND_ROUND) == 0
379 : : because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
380 : : to 2/2.
381 : : */
382 : : gint gnc_numeric_same(gnc_numeric a, gnc_numeric b,
383 : : gint64 denom, gint how);
384 : : /** @} */
385 : :
386 : : /** @name Arithmetic Operations
387 : : @{
388 : : */
389 : : /** Return a+b. */
390 : : gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b,
391 : : gint64 denom, gint how);
392 : :
393 : : /** Return a-b. */
394 : : gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
395 : : gint64 denom, gint how);
396 : :
397 : : /** Multiply a times b, returning the product. An overflow
398 : : * may occur if the result of the multiplication can't
399 : : * be represented as a ratio of 64-bit int's after removing
400 : : * common factors.
401 : : */
402 : : gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
403 : : gint64 denom, gint how);
404 : :
405 : : /** Division. Note that division can overflow, in the following
406 : : * sense: if we write x=a/b and y=c/d then x/y = (a*d)/(b*c)
407 : : * If, after eliminating all common factors between the numerator
408 : : * (a*d) and the denominator (b*c), then if either the numerator
409 : : * and/or the denominator are *still* greater than 2^63, then
410 : : * the division has overflowed.
411 : : */
412 : : gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y,
413 : : gint64 denom, gint how);
414 : : /** Returns a newly created gnc_numeric that is the negative of the
415 : : * given gnc_numeric value. For a given gnc_numeric "a/b" the returned
416 : : * value is "-a/b". */
417 : : gnc_numeric gnc_numeric_neg(gnc_numeric a);
418 : :
419 : : /** Returns a newly created gnc_numeric that is the absolute value of
420 : : * the given gnc_numeric value. For a given gnc_numeric "a/b" the
421 : : * returned value is "|a/b|". */
422 : : gnc_numeric gnc_numeric_abs(gnc_numeric a);
423 : :
424 : : /**
425 : : * Shortcut for common case: gnc_numeric_add(a, b, GNC_DENOM_AUTO,
426 : : * GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
427 : : */
428 : : static inline
429 : 248614 : gnc_numeric gnc_numeric_add_fixed(gnc_numeric a, gnc_numeric b)
430 : : {
431 : 248614 : return gnc_numeric_add(a, b, GNC_DENOM_AUTO,
432 : 200017 : GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
433 : : }
434 : :
435 : : /**
436 : : * Shortcut for most common case: gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
437 : : * GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
438 : : */
439 : : static inline
440 : 98 : gnc_numeric gnc_numeric_sub_fixed(gnc_numeric a, gnc_numeric b)
441 : : {
442 : 98 : return gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
443 : 8 : GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
444 : : }
445 : : /** @} */
446 : :
447 : :
448 : : /** @name Change Denominator
449 : : @{
450 : : */
451 : : /** Change the denominator of a gnc_numeric value to the
452 : : * specified denominator under standard arguments
453 : : * 'denom' and 'how'.
454 : : */
455 : : gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom,
456 : : gint how);
457 : :
458 : : /** Return input after reducing it by Greater Common Factor (GCF)
459 : : * elimination */
460 : : gnc_numeric gnc_numeric_reduce(gnc_numeric n);
461 : :
462 : : /** Attempt to convert the denominator to an exact power of ten without
463 : : * rounding.
464 : : *
465 : : * @param a the ::gnc_numeric value to convert
466 : : *
467 : : * @param max_decimal_places the number of decimal places of the
468 : : * converted value. This parameter may be @c NULL.
469 : : *
470 : : * @return @c TRUE if @a a has been converted or was already decimal.
471 : : * Otherwise, @c FALSE is returned and @a a and @a max_decimal_places
472 : : * remain unchanged.
473 : : ********************************************************************/
474 : : gboolean gnc_numeric_to_decimal(gnc_numeric * a,
475 : : guint8 * max_decimal_places);
476 : :
477 : : /** Invert a gnc_numeric.
478 : : * Much faster than dividing 1 by it.
479 : : * @param num The number to be inverted
480 : : * @return a gnc_numeric that is the inverse of num
481 : : */
482 : : gnc_numeric gnc_numeric_invert (gnc_numeric num);
483 : : /** @} */
484 : :
485 : : /** @name GValue
486 : : @{
487 : : */
488 : : GType gnc_numeric_get_type( void );
489 : : #define GNC_TYPE_NUMERIC (gnc_numeric_get_type ())
490 : :
491 : : #ifdef __cplusplus
492 : : }
493 : : #endif
494 : :
495 : : #endif
|