LCOV - code coverage report
Current view: top level - libgnucash/engine - gnc-numeric.h (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 100.0 % 16 16
Test Date: 2026-11-02 18:19:43 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            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
        

Generated by: LCOV version 2.0-1