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: 2025-02-07 16:25:45 Functions: 100.0 % 4 4
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     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                 :     3991610 :     GncInt128(T lower) : GncInt128(INT64_C(0), static_cast<int64_t>(lower))
      93                 :     3991610 :     {}
      94                 :     3951639 :     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