1 /********************************************************************
2 * qofnumeric.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 See \ref qofnumericexample
40
41 @{ */
42 /** @file qofnumeric.h
43 @brief An exact-rational-number library for QOF.
44 @author Copyright (C) 2000 Bill Gribble
45 @author Copyright (C) 2004 Linas Vepstas <linas@linas.org>
46 @author Copyright (c) 2006 Neil Williams <linux@codehelp.co.uk>
47 */
48
49 #ifndef QOF_NUMERIC_H
50 #define QOF_NUMERIC_H
51
52 struct _QofNumeric
53 {
54 gint64 num;
55 gint64 denom;
56 };
57
58 /** @brief A rational-number type
59 *
60 * This is a rational number, defined by numerator and denominator. */
61 typedef struct _QofNumeric QofNumeric;
62
63 /** @name Standard Arguments to most functions
64
65 Most of the QofNumeric arithmetic functions take two arguments
66 in addition to their numeric args: 'denom', which is the denominator
67 to use in the output QofNumeric object, and 'how'. which
68 describes how the arithmetic result is to be converted to that
69 denominator. This combination of output denominator and rounding policy
70 allows the results of financial and other rational computations to be
71 properly rounded to the appropriate units.
72
73 Valid values for denom are:
74 QOF_DENOM_AUTO -- compute denominator exactly
75 integer n -- Force the denominator of the result to be this integer
76 QOF_DENOM_RECIPROCAL -- Use 1/n as the denominator (???huh???)
77
78 Valid values for 'how' are bitwise combinations of zero or one
79 "rounding instructions" with zero or one "denominator types".
80 Valid rounding instructions are:
81 QOF_HOW_RND_FLOOR
82 QOF_HOW_RND_CEIL
83 QOF_HOW_RND_TRUNC
84 QOF_HOW_RND_PROMOTE
85 QOF_HOW_RND_ROUND_HALF_DOWN
86 QOF_HOW_RND_ROUND_HALF_UP
87 QOF_HOW_RND_ROUND
88 QOF_HOW_RND_NEVER
89
90 The denominator type specifies how to compute a denominator if
91 QOF_DENOM_AUTO is specified as the 'denom'. Valid
92 denominator types are:
93 QOF_HOW_DENOM_EXACT
94 QOF_HOW_DENOM_REDUCE
95 QOF_HOW_DENOM_LCD
96 QOF_HOW_DENOM_FIXED
97 QOF_HOW_DENOM_SIGFIGS(N)
98
99 To use traditional rational-number operational semantics (all results
100 are exact and are reduced to relatively-prime fractions) pass the
101 argument QOF_DENOM_AUTO as 'denom' and
102 QOF_HOW_DENOM_REDUCE| QOF_HOW_RND_NEVER as 'how'.
103
104 To enforce strict financial semantics (such that all operands must have
105 the same denominator as each other and as the result), use
106 QOF_DENOM_AUTO as 'denom' and
107 QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER as 'how'.
108 @{
109 */
110
111 /** \brief bitmasks for HOW flags.
112
113 * bits 8-15 of 'how' are reserved for the number of significant
114 * digits to use in the output with QOF_HOW_DENOM_SIGFIG
115 */
116 #define QOF_NUMERIC_RND_MASK 0x0000000f
117 #define QOF_NUMERIC_DENOM_MASK 0x000000f0
118 #define QOF_NUMERIC_SIGFIGS_MASK 0x0000ff00
119
120 /** \brief Rounding/Truncation modes for operations.
121
122 * Rounding instructions control how fractional parts in the specified
123 * denominator affect the result. For example, if a computed result is
124 * "3/4" but the specified denominator for the return value is 2, should
125 * the return value be "1/2" or "2/2"?
126 *
127 * Possible rounding instructions are:
128 */
129 enum
130 {
131 /** Round toward -infinity */
132 QOF_HOW_RND_FLOOR = 0x01,
133
134 /** Round toward +infinity */
135 QOF_HOW_RND_CEIL = 0x02,
136
137 /** Truncate fractions (round toward zero) */
138 QOF_HOW_RND_TRUNC = 0x03,
139
140 /** Promote fractions (round away from zero) */
141 QOF_HOW_RND_PROMOTE = 0x04,
142
143 /** Round to the nearest integer, rounding toward zero
144 * when there are two equidistant nearest integers.
145 */
146 QOF_HOW_RND_ROUND_HALF_DOWN = 0x05,
147
148 /** Round to the nearest integer, rounding away from zero
149 * when there are two equidistant nearest integers.
150 */
151 QOF_HOW_RND_ROUND_HALF_UP = 0x06,
152
153 /** Use unbiased ("banker's") rounding. This rounds to the
154 * nearest integer, and to the nearest even integer when there
155 * are two equidistant nearest integers. This is generally the
156 * one you should use for financial quantities.
157 */
158 QOF_HOW_RND_ROUND = 0x07,
159
160 /** Never round at all, and signal an error if there is a
161 * fractional result in a computation.
162 */
163 QOF_HOW_RND_NEVER = 0x08
164 };
165
166 /** How to compute a denominator, or'ed into the "how" field. */
167 enum
168 {
169 /** Use any denominator which gives an exactly correct ratio of
170 * numerator to denominator. Use EXACT when you do not wish to
171 * lose any information in the result but also do not want to
172 * spend any time finding the "best" denominator.
173 */
174 QOF_HOW_DENOM_EXACT = 0x10,
175
176 /** Reduce the result value by common factor elimination,
177 * using the smallest possible value for the denominator that
178 * keeps the correct ratio. The numerator and denominator of
179 * the result are relatively prime.
180 */
181 QOF_HOW_DENOM_REDUCE = 0x20,
182
183 /** Find the least common multiple of the arguments' denominators
184 * and use that as the denominator of the result.
185 */
186 QOF_HOW_DENOM_LCD = 0x30,
187
188 /** All arguments are required to have the same denominator,
189 * that denominator is to be used in the output, and an error
190 * is to be signaled if any argument has a different denominator.
191 */
192 QOF_HOW_DENOM_FIXED = 0x40,
193
194 /** Round to the number of significant figures given in the rounding
195 * instructions by the QOF_HOW_DENOM_SIGFIGS () macro.
196 */
197 QOF_HOW_DENOM_SIGFIG = 0x50
198 };
199
200 /** Build a 'how' value that will generate a denominator that will
201 * keep at least n significant figures in the result.
202 */
203 #define QOF_HOW_DENOM_SIGFIGS( n ) ( ((( n ) & 0xff) << 8) | QOF_HOW_DENOM_SIGFIG)
204 #define QOF_HOW_GET_SIGFIGS( a ) ( (( a ) & 0xff00 ) >> 8)
205
206 /** Error codes */
207 typedef enum
208 {
209 QOF_ERROR_OK = 0, /**< No error */
210 QOF_ERROR_ARG = -1, /**< Argument is not a valid number */
211 QOF_ERROR_OVERFLOW = -2, /**< Intermediate result overflow */
212
213 /** QOF_HOW_DENOM_FIXED was specified, but argument denominators differed. */
214 QOF_ERROR_DENOM_DIFF = -3,
215
216 /** QOF_HOW_RND_NEVER was specified, but the result could not be
217 * converted to the desired denominator without a remainder. */
218 QOF_ERROR_REMAINDER = -4
219 } QofNumericErrorCode;
220
221
222 /** Values that can be passed as the 'denom' argument.
223 * The include a positive number n to be used as the
224 * denominator of the output value. Other possibilities
225 * include the list below:
226 */
227
228 /** Compute an appropriate denominator automatically. Flags in
229 * the 'how' argument will specify how to compute the denominator.
230 */
231 #define QOF_DENOM_AUTO 0
232
233 /** Use the value 1/n as the denominator of the output value. */
234 #define QOF_DENOM_RECIPROCAL( a ) (- ( a ))
235
236 /** @} */
237
238 /** @name Constructors
239 @{
240 */
241 /** Make a QofNumeric from numerator and denominator */
242 static inline QofNumeric
qof_numeric_create(gint64 num,gint64 denom)243 qof_numeric_create (gint64 num, gint64 denom)
244 {
245 QofNumeric out;
246 out.num = num;
247 out.denom = denom;
248 return out;
249 }
250
251 /** create a zero-value QofNumeric */
252 static inline QofNumeric
qof_numeric_zero(void)253 qof_numeric_zero (void)
254 {
255 return qof_numeric_create (0, 1);
256 }
257
258 /** Convert a floating-point number to a QofNumeric.
259 * Both 'denom' and 'how' are used as in arithmetic,
260 * but QOF_DENOM_AUTO is not recognized; a denominator
261 * must be specified either explicitctly or through sigfigs.
262 */
263 QofNumeric
264 qof_numeric_from_double (gdouble in, gint64 denom, gint how);
265
266 /** Read a QofNumeric from str, skipping any leading whitespace.
267 * Return TRUE on success and store the resulting value in "n".
268 * Return NULL on error. */
269 gboolean
270 qof_numeric_from_string (const gchar * str, QofNumeric * n);
271
272 /** Create a QofNumeric object that signals the error condition
273 * noted by error_code, rather than a number.
274 */
275 QofNumeric
276 qof_numeric_error (QofNumericErrorCode error_code);
277 /** @} */
278
279 /** @name Value Accessors
280 @{
281 */
282 /** Return numerator */
283 static inline gint64
qof_numeric_num(QofNumeric a)284 qof_numeric_num (QofNumeric a)
285 {
286 return a.num;
287 }
288
289 /** Return denominator */
290 static inline gint64
qof_numeric_denom(QofNumeric a)291 qof_numeric_denom (QofNumeric a)
292 {
293 return a.denom;
294 }
295
296 /** Convert numeric to floating-point value. */
297 gdouble
298 qof_numeric_to_double (QofNumeric in);
299
300 /** Convert to string. The returned buffer is to be g_free'd by the
301 * caller (it was allocated through g_strdup) */
302 gchar *
303 qof_numeric_to_string (QofNumeric n);
304
305 /** Convert to string. Uses a static, non-thread-safe buffer.
306 * For internal use only. */
307 gchar *
308 qof_numeric_dbg_to_string (QofNumeric n);
309 /** @}*/
310
311 /** @name Comparisons and Predicates
312 @{
313 */
314 /** Check for error signal in value. Returns QOF_ERROR_OK (==0) if
315 * the number appears to be valid, otherwise it returns the
316 * type of error. Error values always have a denominator of zero.
317 */
318 QofNumericErrorCode
319 qof_numeric_check (QofNumeric a);
320
321 /** Returns 1 if a>b, -1 if b>a, 0 if a == b */
322 gint
323 qof_numeric_compare (QofNumeric a, QofNumeric b);
324
325 /** Returns 1 if the given QofNumeric is 0 (zero), else returns 0. */
326 gboolean
327 qof_numeric_zero_p (QofNumeric a);
328
329 /** Returns 1 if a < 0, otherwise returns 0. */
330 gboolean
331 qof_numeric_negative_p (QofNumeric a);
332
333 /** Returns 1 if a > 0, otherwise returns 0. */
334 gboolean
335 qof_numeric_positive_p (QofNumeric a);
336
337 /** Equivalence predicate: Returns TRUE (1) if a and b are
338 * exactly the same (have the same numerator and denominator)
339 */
340 gboolean
341 qof_numeric_eq (QofNumeric a, QofNumeric b);
342
343 /** Equivalence predicate: Returns TRUE (1) if a and b represent
344 * the same number. That is, return TRUE if the ratios, when
345 * reduced by eliminating common factors, are identical.
346 */
347 gboolean
348 qof_numeric_equal (QofNumeric a, QofNumeric b);
349
350 /** Equivalence predicate:
351 * Convert both a and b to denom using the
352 * specified DENOM and method HOW, and compare numerators
353 * the results using QofNumeric_equal.
354 *
355 For example, if a == 7/16 and b == 3/4,
356 QofNumeric_same(a, b, 2, QOF_HOW_RND_TRUNC) == 1
357 because both 7/16 and 3/4 round to 1/2 under truncation. However,
358 QofNumeric_same(a, b, 2, QOF_HOW_RND_ROUND) == 0
359 because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
360 to 2/2.
361 */
362 gint
363 qof_numeric_same (QofNumeric a, QofNumeric b, gint64 denom, gint how);
364 /** @} */
365
366 /** @name Arithmetic Operations
367 @{
368 */
369 /** Return a+b. */
370 QofNumeric
371 qof_numeric_add (QofNumeric a, QofNumeric b,
372 gint64 denom, gint how);
373
374 /** Return a-b. */
375 QofNumeric
376 qof_numeric_sub (QofNumeric a, QofNumeric b,
377 gint64 denom, gint how);
378
379 /** Multiply a times b, returning the product. An overflow
380 * may occur if the result of the multiplication can't
381 * be represented as a ratio of 64-bit int's after removing
382 * common factors.
383 */
384 QofNumeric
385 qof_numeric_mul (QofNumeric a, QofNumeric b,
386 gint64 denom, gint how);
387
388 /** Division. Note that division can overflow, in the following
389 * sense: if we write x=a/b and y=c/d then x/y = (a*d)/(b*c)
390 * If, after eliminating all common factors between the numerator
391 * (a*d) and the denominator (b*c), then if either the numerator
392 * and/or the denominator are *still* greater than 2^63, then
393 * the division has overflowed.
394 */
395 QofNumeric
396 qof_numeric_div (QofNumeric x, QofNumeric y,
397 gint64 denom, gint how);
398 /** Negate the argument */
399 QofNumeric
400 qof_numeric_neg (QofNumeric a);
401
402 /** Return the absolute value of the argument */
403 QofNumeric
404 qof_numeric_abs (QofNumeric a);
405
406 /**
407 * Shortcut for common case: QofNumeric_add(a, b, QOF_DENOM_AUTO,
408 * QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
409 */
410 static inline QofNumeric
qof_numeric_add_fixed(QofNumeric a,QofNumeric b)411 qof_numeric_add_fixed (QofNumeric a, QofNumeric b)
412 {
413 return qof_numeric_add (a, b, QOF_DENOM_AUTO,
414 QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
415 }
416
417 /**
418 * Shortcut for most common case: QofNumeric_sub(a, b, QOF_DENOM_AUTO,
419 * QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
420 */
421 static inline QofNumeric
qof_numeric_sub_fixed(QofNumeric a,QofNumeric b)422 qof_numeric_sub_fixed (QofNumeric a, QofNumeric b)
423 {
424 return qof_numeric_sub (a, b, QOF_DENOM_AUTO,
425 QOF_HOW_DENOM_FIXED | QOF_HOW_RND_NEVER);
426 }
427
428 /** @} */
429
430 /** @name Arithmetic Functions with Exact Error Returns
431 @{
432 */
433 /** The same as QofNumeric_add, but uses 'error' for accumulating
434 * conversion roundoff error. */
435 QofNumeric
436 qof_numeric_add_with_error (QofNumeric a, QofNumeric b,
437 gint64 denom, gint how,
438 QofNumeric * error);
439
440 /** The same as QofNumeric_sub, but uses error for accumulating
441 * conversion roundoff error. */
442 QofNumeric
443 qof_numeric_sub_with_error (QofNumeric a, QofNumeric b,
444 gint64 denom, gint how,
445 QofNumeric * error);
446
447 /** The same as QofNumeric_mul, but uses error for
448 * accumulating conversion roundoff error.
449 */
450 QofNumeric
451 qof_numeric_mul_with_error (QofNumeric a, QofNumeric b,
452 gint64 denom, gint how,
453 QofNumeric * error);
454
455 /** The same as QofNumeric_div, but uses error for
456 * accumulating conversion roundoff error.
457 */
458 QofNumeric
459 qof_numeric_div_with_error (QofNumeric a, QofNumeric b,
460 gint64 denom, gint how,
461 QofNumeric * error);
462 /** @} */
463
464 /** @name Change Denominator
465 @{
466 */
467 /** Change the denominator of a QofNumeric value to the
468 * specified denominator under standard arguments
469 * 'denom' and 'how'.
470 */
471 QofNumeric
472 qof_numeric_convert (QofNumeric in, gint64 denom, gint how);
473
474 /** Same as QofNumeric_convert, but return a remainder
475 * value for accumulating conversion error.
476 */
477 QofNumeric
478 qof_numeric_convert_with_error (QofNumeric in, gint64 denom,
479 gint how, QofNumeric * error);
480
481 /** Return input after reducing it by Greated Common Factor (GCF)
482 * elimination */
483 QofNumeric qof_numeric_reduce (QofNumeric in);
484 /** @} */
485
486 /** @name Deprecated, backwards-compatible definitions
487 @{
488 */
489 #define QOF_RND_FLOOR QOF_HOW_RND_FLOOR
490 #define QOF_RND_CEIL QOF_HOW_RND_CEIL
491 #define QOF_RND_TRUNC QOF_HOW_RND_TRUNC
492 #define QOF_RND_PROMOTE QOF_HOW_RND_PROMOTE
493 #define QOF_RND_ROUND_HALF_DOWN QOF_HOW_RND_ROUND_HALF_DOWN
494 #define QOF_RND_ROUND_HALF_UP QOF_HOW_RND_ROUND_HALF_UP
495 #define QOF_RND_ROUND QOF_HOW_RND_ROUND
496 #define QOF_RND_NEVER QOF_HOW_RND_NEVER
497
498 #define QOF_DENOM_EXACT QOF_HOW_DENOM_EXACT
499 #define QOF_DENOM_REDUCE QOF_HOW_DENOM_REDUCE
500 #define QOF_DENOM_LCD QOF_HOW_DENOM_LCD
501 #define QOF_DENOM_FIXED QOF_HOW_DENOM_FIXED
502 #define QOF_DENOM_SIGFIG QOF_HOW_DENOM_SIGFIG
503
504 #define QOF_DENOM_SIGFIGS(X) QOF_HOW_DENOM_SIGFIGS(X)
505 #define QOF_NUMERIC_GET_SIGFIGS(X) QOF_HOW_GET_SIGFIGS(X)
506 /** @} */
507 /** @} */
508 #endif
509