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

            Line data    Source code
       1              : /********************************************************************
       2              :  * qofmath128.h -- an 128-bit integer library                       *
       3              :  * Copyright (C) 2004 Linas Vepstas <linas@linas.org>               *
       4              :  * Copyright (C) 2014 John Ralls <jralls@ceridwen.us>               *
       5              :  *                                                                  *
       6              :  * This program is free software; you can redistribute it and/or    *
       7              :  * modify it under the terms of the GNU General Public License as   *
       8              :  * published by the Free Software Foundation; either version 2 of   *
       9              :  * the License, or (at your option) any later version.              *
      10              :  *                                                                  *
      11              :  * This program is distributed in the hope that it will be useful,  *
      12              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      14              :  * GNU General Public License for more details.                     *
      15              :  *                                                                  *
      16              :  * You should have received a copy of the GNU General Public License*
      17              :  * along with this program; if not, contact:                        *
      18              :  *                                                                  *
      19              :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      20              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      21              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      22              :  *                                                                  *
      23              :  *******************************************************************/
      24              : 
      25              : #ifndef GNCINT128_H
      26              : #define GNCINT128_H
      27              : 
      28              : #ifndef __STDC_LIMIT_MACROS
      29              : #define  __STDC_LIMIT_MACROS 1
      30              : #endif
      31              : #ifndef __STDC_CONSTANT_MACROS
      32              : #define  __STDC_CONSTANT_MACROS 1
      33              : #endif
      34              : #ifndef __STDC_FORMAT_MACROS
      35              : #define  __STDC_FORMAT_MACROS 1
      36              : #endif
      37              : #include <inttypes.h>
      38              : 
      39              : #include <stdexcept>
      40              : #include <string>
      41              : #include <ostream>
      42              : #include <type_traits>
      43              : 
      44              : //using std::string;
      45              : /** @addtogroup GncInt128
      46              :  * @ingroup QOF
      47              :  * @{
      48              :  * @brief provides a 125-bit int as a base class for GncNumeric.
      49              :  *
      50              :  * In order to make space for the status flags the upper leg is limited to
      51              :  * 0x1fffffffffffffff. Attempting to construct a GncInt128 with a larger upper
      52              :  * leg will throw a std::overflow_error.
      53              :  *
      54              :  * All the usual operators are provided. Only the constructors and explicit
      55              :  * integer conversions throw; all other errors are indicated by the overflow and
      56              :  * NaN ("Not a Number") flags. Note that performing any operation on an
      57              :  * overflowed or NaN Gncint128 will yield an overflowed or NaN result, so
      58              :  * calling routines need not check until the end of a chained calculation.
      59              :  * GncInt128 uses implicit copy and move constructors and implicit destructor.
      60              :  */
      61              : class GncInt128
      62              : {
      63              :     uint64_t m_hi;
      64              :     uint64_t m_lo;
      65              : 
      66              : public:
      67              :     static const unsigned int flagbits = 3;
      68              :     static const unsigned int numlegs = 2;
      69              :     static const unsigned int legbits = 64;
      70              :     static const unsigned int maxbits = legbits * numlegs - flagbits;
      71              : 
      72              : enum // Values for m_flags
      73              : {
      74              :     pos = 0,
      75              :     neg = 1,
      76              :     overflow = 2,
      77              :     NaN = 4
      78              : };
      79              : /** @addtogroup Constructors Constructors
      80              :  *  Constructors are templated so that a GncInt128 can be constructed from any
      81              :  *  arbitrary integer type or pair of integer types.
      82              :  * @note If the two parameters are of differing sign, it's taken to
      83              :  * mean that the lower magnitude is *reducing* the magnitude of the
      84              :  * upper, so the lower magnitude will be subtracted from UINT64_MAX to
      85              :  * obtain the lower limb value.
      86              : *  @{
      87              :  */
      88              : /** Default constructor. Makes 0. */
      89              :     GncInt128();
      90              :     template <typename T,
      91              :               std::enable_if_t<std::is_integral<T>::value, bool> = true>
      92      2555229 :     GncInt128(T lower) : GncInt128(INT64_C(0), static_cast<int64_t>(lower))
      93      2555229 :     {}
      94      2280901 :     GncInt128(uint64_t lower) : GncInt128 {UINT64_C(0), lower} {}
      95              : /** Double-integer constructor template.
      96              :  */
      97              :     template <typename T, typename U,
      98              :               std::enable_if_t<(std::is_integral<T>::value &&
      99              :               std::is_integral<U>::value), bool> = true>
     100              :     GncInt128(T upper, U lower, unsigned char flags = '\0') :
     101              :         GncInt128 {static_cast<int64_t>(upper),
     102              :                    static_cast<int64_t>(lower), flags} {}
     103              : 
     104              :     GncInt128 (int64_t upper, int64_t lower, unsigned char flags = '\0');
     105              :     template <typename T,
     106              :               std::enable_if_t<std::is_integral<T>::value, bool> = true>
     107              :     GncInt128(T upper, uint64_t lower) :
     108              :         GncInt128 {static_cast<int64_t>(upper), lower} {}
     109              : 
     110              :     GncInt128 (int64_t upper, uint64_t lower, unsigned char flags = '\0');
     111              :     GncInt128 (uint64_t upper, uint64_t lower, unsigned char flags = '\0');
     112              : /** @} */
     113              : /**
     114              :  * Clear the object.
     115              :  *
     116              :  * Sets all member variables to zero.
     117              :  * @return A reference to the object for chaining.
     118              :  */
     119              :     GncInt128& zero() noexcept;
     120              : 
     121              : /**
     122              :  * Compare function.
     123              :  *
     124              :  * @return -1 if the object is less than the parameter, 0 if they're
     125              :  * equal, and 1 if the object is greater.
     126              :  */
     127              :     int cmp (const GncInt128& b) const noexcept;
     128              : 
     129              : /**
     130              :  * Computes the Greatest Common Divisor between the object and parameter
     131              :  *
     132              :  * @return A GncInt128 having the GCD.
     133              :  */
     134              :     GncInt128 gcd (GncInt128 b) const noexcept;
     135              : /**
     136              :  * Computes the Least Common Multiple between the object and parameter
     137              :  *
     138              :  * @return A GncInt128 having the LCM.
     139              :  */
     140              :     GncInt128 lcm (const GncInt128& b) const noexcept;
     141              : 
     142              : /**
     143              :  * Computes the object raised to the parameter's power
     144              :  *
     145              :  * @param b The power to raise this to. No point in taking a GncInt128, any
     146              :  * value greater than 128 would overflow on any value other than 1.
     147              :  * @return A GncInt128
     148              :  */
     149              :     GncInt128 pow (unsigned int n) const noexcept;
     150              : 
     151              : /**
     152              :  * Computes a quotient and a remainder, passed as reference parameters.
     153              :  *
     154              :  * 'this' is the dividend. The quotient and remainder args must be initialized
     155              :  * to zero.
     156              :  * @param d The divisor
     157              :  * @param q The quotient; will be NaN if divisor = 0
     158              :  * @param r The remainder; will be 0 if divisor = 0
     159              :  */
     160              :     void div (const GncInt128& d, GncInt128& q, GncInt128& r) const noexcept;
     161              : 
     162              : /**
     163              :  * Explicit conversion to int64_t.
     164              :  *
     165              :  * @return A int64_t
     166              :  * @throws std::overflow_error if the object's value is > INT64_MAX or NaN.
     167              :  * @throws std::underflow_error if the object's value is < INT64_MIN
     168              :  */
     169              :     explicit operator int64_t() const;
     170              : /**
     171              :  * Explicit conversion to uint64_t.
     172              :  *
     173              :  * @return A uint64_t
     174              :  * @throws std::overflow_error if the object's value is > UINT64_MAX or NaN.
     175              :  * @throws std::underflow_error if the object's value is < 0.
     176              :  */
     177              :     explicit operator uint64_t() const;
     178              : 
     179              : /**
     180              :  * @return true if the object value is < 0
     181              :  */
     182              :     bool isNeg () const noexcept;
     183              : /**
     184              :  * @return true if the object value is > INT64_MAX or < INT64_MIN
     185              :  */
     186              :     bool isBig () const noexcept;
     187              : /**
     188              :  * @return true if a calculation has produced a result of larger
     189              :  * magnitude than can be contained in the 128 bits available.
     190              :  */
     191              :     bool isOverflow () const noexcept;
     192              : /**
     193              :  * @return true if an illegal calculation has occurred.
     194              :  */
     195              :     bool isNan () const noexcept;
     196              : /**
     197              :  * @return true if the object represents 0.
     198              :  */
     199              :     bool isZero() const noexcept;
     200              : /**
     201              :  * @return true if neither the overflow nor nan flags are set.
     202              :  */
     203              :     bool valid() const noexcept;
     204              : 
     205              : /**
     206              :  * @return the number of bits used to represent the value
     207              :  */
     208              :     unsigned int bits() const noexcept;
     209              : 
     210              : /**
     211              :  * Fills a supplied buffer with a representation of the number in base 10. If
     212              :  * the GncInt128 is overflowed or NaN it will contain the words "Overflow" or
     213              :  * "NaN" respectively.
     214              :  *
     215              :  * @param buf char[41], 39 digits plus sign and trailing 0.
     216              :  * @return pointer to the buffer for convenience
     217              :  */
     218              :     char* asCharBufR(char* buf, uint32_t size) const noexcept;
     219              : 
     220              :     GncInt128 abs() const noexcept;
     221              : 
     222              :     GncInt128 operator-() const noexcept;
     223              :     explicit operator bool() const noexcept;
     224              : 
     225              :     GncInt128& operator++ () noexcept;
     226              :     GncInt128& operator++ (int) noexcept;
     227              :     GncInt128& operator-- () noexcept;
     228              :     GncInt128& operator-- (int) noexcept;
     229              :     GncInt128& operator<<= (unsigned int i) noexcept;
     230              :     GncInt128& operator>>= (unsigned int i) noexcept;
     231              :     GncInt128& operator+= (const GncInt128& b) noexcept;
     232              :     GncInt128& operator-= (const GncInt128& b) noexcept;
     233              :     GncInt128& operator*= (const GncInt128& b) noexcept;
     234              :     GncInt128& operator/= (const GncInt128& b) noexcept;
     235              :     GncInt128& operator%= (const GncInt128& b) noexcept;
     236              :     GncInt128& operator&= (const GncInt128& b) noexcept;
     237              :     GncInt128& operator|= (const GncInt128& b) noexcept;
     238              :     GncInt128& operator^= (const GncInt128& b) noexcept;
     239              : 
     240              : };
     241              : 
     242              : static const GncInt128 k_gncint128_Max {UINT64_MAX, UINT64_MAX, GncInt128::pos};
     243              : static const GncInt128 k_gncint128_Min {UINT64_MAX, UINT64_MAX, GncInt128::neg};
     244              : 
     245              : GncInt128 operator+ (GncInt128 a, const GncInt128& b) noexcept;
     246              : GncInt128 operator- (GncInt128 a, const GncInt128& b) noexcept;
     247              : GncInt128 operator* (GncInt128 a, const GncInt128& b) noexcept;
     248              : GncInt128 operator/ (GncInt128 a, const GncInt128& b) noexcept;
     249              : GncInt128 operator% (GncInt128 a, const GncInt128& b) noexcept;
     250              : GncInt128 operator& (GncInt128 a, const GncInt128& b) noexcept;
     251              : GncInt128 operator| (GncInt128 a, const GncInt128& b) noexcept;
     252              : GncInt128 operator^ (GncInt128 a, const GncInt128& b) noexcept;
     253              : GncInt128 operator<< (GncInt128 a, unsigned int b) noexcept;
     254              : GncInt128 operator>> (GncInt128 a, unsigned int b) noexcept;
     255              : 
     256              : bool operator== (const GncInt128& a, const GncInt128& b) noexcept;
     257              : bool operator!= (const GncInt128& a, const GncInt128& b) noexcept;
     258              : bool operator<= (const GncInt128& a, const GncInt128& b) noexcept;
     259              : bool operator>= (const GncInt128& a, const GncInt128& b) noexcept;
     260              : bool operator< (const GncInt128& a, const GncInt128& b) noexcept;
     261              : bool operator> (const GncInt128& a, const GncInt128& b) noexcept;
     262              : 
     263              : std::ostream& operator<< (std::ostream&, const GncInt128&) noexcept;
     264              : 
     265              : /** Compute the greatest common denominator of two integers
     266              :  */
     267              : GncInt128 gcd (int64_t a, int64_t b);
     268              : 
     269              : /** Compute the least common multiple of two integers
     270              :  */
     271              : GncInt128 lcm (int64_t a, int64_t b);
     272              : 
     273              : #endif //GNCINT128_H
     274              : 
     275              : /** @} */
        

Generated by: LCOV version 2.0-1