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 224216 : gnc_numeric gnc_numeric_create(gint64 num, gint64 denom)
256 : {
257 : gnc_numeric out;
258 224216 : out.num = num;
259 224216 : out.denom = denom;
260 224216 : return out;
261 : }
262 :
263 : /** Returns a newly created gnc_numeric of value zero, that is "0/1". */
264 : static inline
265 197683 : gnc_numeric gnc_numeric_zero(void)
266 : {
267 197683 : 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 11121 : gint64 gnc_numeric_num(gnc_numeric a)
316 : {
317 11121 : return a.num;
318 : }
319 : /** Returns the denominator of the given gnc_numeric value. */
320 : static inline
321 10760 : gint64 gnc_numeric_denom(gnc_numeric a)
322 : {
323 10760 : 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 208318 : gnc_numeric gnc_numeric_add_fixed(gnc_numeric a, gnc_numeric b)
430 : {
431 208318 : return gnc_numeric_add(a, b, GNC_DENOM_AUTO,
432 208318 : 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 8 : gnc_numeric gnc_numeric_sub_fixed(gnc_numeric a, gnc_numeric b)
441 : {
442 8 : 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
|