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 : : /** @} */
|