GnuCash c935c2f+
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Attributes
GncInt128 Class Reference

Public Types

enum  { pos = 0 , neg = 1 , overflow = 2 , NaN = 4 }
 

Public Member Functions

 GncInt128 ()
 Default constructor.
 
template<typename T , std::enable_if_t< std::is_integral< T >::value, bool > = true>
 GncInt128 (T lower)
 
 GncInt128 (uint64_t lower)
 
template<typename T , typename U , std::enable_if_t<(std::is_integral< T >::value &&std::is_integral< U >::value), bool > = true>
 GncInt128 (T upper, U lower, unsigned char flags='\0')
 Double-integer constructor template.
 
 GncInt128 (int64_t upper, int64_t lower, unsigned char flags='\0')
 
template<typename T , std::enable_if_t< std::is_integral< T >::value, bool > = true>
 GncInt128 (T upper, uint64_t lower)
 
 GncInt128 (int64_t upper, uint64_t lower, unsigned char flags='\0')
 
 GncInt128 (uint64_t upper, uint64_t lower, unsigned char flags='\0')
 
GncInt128zero () noexcept
 Clear the object.
 
int cmp (const GncInt128 &b) const noexcept
 Compare function.
 
GncInt128 gcd (GncInt128 b) const noexcept
 Computes the Greatest Common Divisor between the object and parameter.
 
GncInt128 lcm (const GncInt128 &b) const noexcept
 Computes the Least Common Multiple between the object and parameter.
 
GncInt128 pow (unsigned int n) const noexcept
 Computes the object raised to the parameter's power.
 
void div (const GncInt128 &d, GncInt128 &q, GncInt128 &r) const noexcept
 Computes a quotient and a remainder, passed as reference parameters.
 
 operator int64_t () const
 Explicit conversion to int64_t.
 
 operator uint64_t () const
 Explicit conversion to uint64_t.
 
bool isNeg () const noexcept
 
bool isBig () const noexcept
 
bool isOverflow () const noexcept
 
bool isNan () const noexcept
 
bool isZero () const noexcept
 
bool valid () const noexcept
 
unsigned int bits () const noexcept
 
char * asCharBufR (char *buf, uint32_t size) const noexcept
 Fills a supplied buffer with a representation of the number in base 10.
 
GncInt128 abs () const noexcept
 
GncInt128 operator- () const noexcept
 
 operator bool () const noexcept
 
GncInt128operator++ () noexcept
 
GncInt128operator++ (int) noexcept
 
GncInt128operator-- () noexcept
 
GncInt128operator-- (int) noexcept
 
GncInt128operator<<= (unsigned int i) noexcept
 
GncInt128operator>>= (unsigned int i) noexcept
 
GncInt128operator+= (const GncInt128 &b) noexcept
 
GncInt128operator-= (const GncInt128 &b) noexcept
 
GncInt128operator*= (const GncInt128 &b) noexcept
 
GncInt128operator/= (const GncInt128 &b) noexcept
 
GncInt128operator%= (const GncInt128 &b) noexcept
 
GncInt128operator&= (const GncInt128 &b) noexcept
 
GncInt128operator|= (const GncInt128 &b) noexcept
 
GncInt128operator^= (const GncInt128 &b) noexcept
 

Static Public Attributes

static const unsigned int flagbits = 3
 
static const unsigned int numlegs = 2
 
static const unsigned int legbits = 64
 
static const unsigned int maxbits = legbits * numlegs - flagbits
 

Detailed Description

Definition at line 61 of file gnc-int128.hpp.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum

Definition at line 72 of file gnc-int128.hpp.

73{
74 pos = 0,
75 neg = 1,
76 overflow = 2,
77 NaN = 4
78};

Member Function Documentation

◆ abs()

GncInt128 GncInt128::abs ( ) const
noexcept

Definition at line 284 of file gnc-int128.cpp.

285{
286 if (isNeg())
287 return operator-();
288
289 return *this;
290}
bool isNeg() const noexcept

◆ asCharBufR()

char * GncInt128::asCharBufR ( char *  buf,
uint32_t  size 
) const
noexcept

Fills a supplied buffer with a representation of the number in base 10.

If the GncInt128 is overflowed or NaN it will contain the words "Overflow" or "NaN" respectively.

Parameters
bufchar[41], 39 digits plus sign and trailing 0.
Returns
pointer to the buffer for convenience

Definition at line 918 of file gnc-int128.cpp.

919{
920 if (isOverflow())
921 {
922 snprintf (buf, size, "%s", "Overflow");
923 return buf;
924 }
925 if (isNan())
926 {
927 snprintf (buf, size, "%s", "NaN");
928 return buf;
929 }
930 if (isZero())
931 {
932 snprintf (buf, size, "%d", 0);
933 return buf;
934 }
935 uint64_t d[dec_array_size] {};
936 decimal_from_binary(d, get_num(m_hi), m_lo);
937 char* next = buf;
938 char neg {'-'};
939
940 if (isNeg()) *(next++) = neg;
941 bool trailing {false};
942 for (unsigned int i {dec_array_size}; i; --i)
943 if (d[i - 1] || trailing)
944 {
945 uint32_t new_size = size - (next - buf);
946 if (trailing)
947 next += snprintf (next, new_size, "%8.8" PRIu64, d[i - 1]);
948 else
949 next += snprintf (next, new_size, "%" PRIu64, d[i - 1]);
950
951 trailing = true;
952 }
953
954 return buf;
955}
bool isOverflow() const noexcept
bool isZero() const noexcept
bool isNan() const noexcept

◆ bits()

unsigned int GncInt128::bits ( ) const
noexcept
Returns
the number of bits used to represent the value

Definition at line 293 of file gnc-int128.cpp.

294{
295 auto hi = get_num(m_hi);
296 unsigned int bits {static_cast<unsigned int>(hi == 0 ? 0 : 64)};
297 uint64_t temp {(hi == 0 ? m_lo : hi)};
298 for (;temp > 0; temp >>= 1)
299 ++bits;
300 return bits;
301}
unsigned int bits() const noexcept

◆ cmp()

int GncInt128::cmp ( const GncInt128 b) const
noexcept

Compare function.

Returns
-1 if the object is less than the parameter, 0 if they're equal, and 1 if the object is greater.

Definition at line 151 of file gnc-int128.cpp.

152{
153 auto flags = get_flags(m_hi);
154 if (flags & (overflow | NaN))
155 return -1;
156 if (b.isOverflow () || b.isNan ())
157 return 1;
158 auto hi = get_num(m_hi);
159 auto bhi = get_num(b.m_hi);
160 if (isZero() && b.isZero()) return 0;
161 if (flags & neg)
162 {
163 if (!b.isNeg()) return -1;
164 if (hi > bhi) return -1;
165 if (hi < bhi) return 1;
166 if (m_lo > b.m_lo) return -1;
167 if (m_lo < b.m_lo) return 1;
168 return 0;
169 }
170 if (b.isNeg()) return 1;
171 if (hi < bhi) return -1;
172 if (hi > bhi) return 1;
173 if (m_lo < b.m_lo) return -1;
174 if (m_lo > b.m_lo) return 1;
175 return 0;
176}

◆ div()

void GncInt128::div ( const GncInt128 d,
GncInt128 q,
GncInt128 r 
) const
noexcept

Computes a quotient and a remainder, passed as reference parameters.

'this' is the dividend. The quotient and remainder args must be initialized to zero.

Parameters
dThe divisor
qThe quotient; will be NaN if divisor = 0
rThe remainder; will be 0 if divisor = 0

Definition at line 723 of file gnc-int128.cpp.

724{
725 // clear remainder and quotient
726 r = GncInt128(0);
727 q = GncInt128(0);
728
729 auto qflags = get_flags(q.m_hi);
730 auto rflags = get_flags(r.m_hi);
731 if (isOverflow() || b.isOverflow())
732 {
733 qflags |= overflow;
734 rflags |= overflow;
735 q.m_hi = set_flags(q.m_hi, qflags);
736 r.m_hi = set_flags(r.m_hi, rflags);
737 return;
738 }
739
740 if (isNan() || b.isNan())
741 {
742 qflags |= NaN;
743 rflags |= NaN;
744 q.m_hi = set_flags(q.m_hi, qflags);
745 r.m_hi = set_flags(r.m_hi, rflags);
746 return;
747 }
748 assert (&q != this);
749 assert (&r != this);
750 assert (&q != &b);
751 assert (&r != &b);
752
753 q.zero(), r.zero();
754 qflags = rflags = 0;
755 if (b.isZero())
756 {
757 qflags |= NaN;
758 rflags |= NaN;
759 q.m_hi = set_flags(q.m_hi, qflags);
760 r.m_hi = set_flags(r.m_hi, rflags);
761 return;
762 }
763
764 if (isNeg())
765 {
766 qflags |= neg;
767 rflags |= neg; // the remainder inherits the dividend's sign
768 }
769
770 if (b.isNeg())
771 qflags ^= neg;
772
773 q.m_hi = set_flags(q.m_hi, qflags);
774 r.m_hi = set_flags(r.m_hi, rflags);
775
776 if (abs() < b.abs())
777 {
778 r = *this;
779 return;
780 }
781 auto hi = get_num(m_hi);
782 auto bhi = get_num(b.m_hi);
783
784 if (hi == 0 && bhi == 0) //let the hardware do it
785 {
786 assert (b.m_lo != 0); // b.m_hi is 0 but b isn't or we didn't get here.
787 q.m_lo = m_lo / b.m_lo;
788 r.m_lo = m_lo % b.m_lo;
789 return;
790 }
791
792 uint64_t u[sublegs + 2] {(m_lo & sublegmask), (m_lo >> sublegbits),
793 (hi & sublegmask), (hi >> sublegbits), 0, 0};
794 uint64_t v[sublegs] {(b.m_lo & sublegmask), (b.m_lo >> sublegbits),
795 (bhi & sublegmask), (bhi >> sublegbits)};
796 auto m = u[3] ? 4 : u[2] ? 3 : u[1] ? 2 : u[0] ? 1 : 0;
797 auto n = v[3] ? 4 : v[2] ? 3 : v[1] ? 2 : v[0] ? 1 : 0;
798 if (m == 0 || n == 0) //Shouldn't happen
799 return;
800 if (n == 1)
801 return div_single_leg (u, m, v[0], q, r);
802
803 return div_multi_leg (u, m, v, n, q, r);
804}
GncInt128 & zero() noexcept
Clear the object.
GncInt128()
Default constructor.

◆ gcd()

GncInt128 GncInt128::gcd ( GncInt128  b) const
noexcept

Computes the Greatest Common Divisor between the object and parameter.

Returns
A GncInt128 having the GCD.

Definition at line 182 of file gnc-int128.cpp.

183{
184 if (b.isZero())
185 return *this;
186 if (isZero())
187 return b;
188
189 if (b.isOverflow() || b.isNan())
190 return b;
191 if (isOverflow() || isNan())
192 return *this;
193
194 GncInt128 a (isNeg() ? -(*this) : *this);
195 if (b.isNeg()) b = -b;
196
197 unsigned int k {};
198 const uint64_t one {1};
199 while (!((a & one) || (b & one))) //B1
200 {
201 a >>= 1;
202 b >>= 1;
203 ++k;
204 }
205 GncInt128 t {a & one ? -b : a}; //B2
206 while (a != b)
207 {
208 while (t && ((t & one) ^ one)) t >>= 1; //B3 & B4
209 if (t.isNeg()) //B5
210 b = -t;
211 else
212 a = t;
213 t = a - b; //B6
214 }
215 return a << k;
216}

◆ isBig()

bool GncInt128::isBig ( ) const
noexcept
Returns
true if the object value is > INT64_MAX or < INT64_MIN

Definition at line 253 of file gnc-int128.cpp.

254{
255 return (get_num(m_hi) || m_lo > INT64_MAX);
256}

◆ isNan()

bool GncInt128::isNan ( ) const
noexcept
Returns
true if an illegal calculation has occurred.

Definition at line 265 of file gnc-int128.cpp.

266{
267 return (get_flags(m_hi) & NaN);
268}

◆ isNeg()

bool GncInt128::isNeg ( ) const
noexcept
Returns
true if the object value is < 0

Definition at line 247 of file gnc-int128.cpp.

248{
249 return (get_flags(m_hi) & neg);
250}

◆ isOverflow()

bool GncInt128::isOverflow ( ) const
noexcept
Returns
true if a calculation has produced a result of larger magnitude than can be contained in the 128 bits available.

Definition at line 259 of file gnc-int128.cpp.

260{
261 return (get_flags(m_hi) & overflow);
262}

◆ isZero()

bool GncInt128::isZero ( ) const
noexcept
Returns
true if the object represents 0.

Definition at line 277 of file gnc-int128.cpp.

278{
279 return ((get_flags(m_hi) & (overflow | NaN)) == 0 &&
280 get_num(m_hi) == 0 && m_lo == 0);
281}

◆ lcm()

GncInt128 GncInt128::lcm ( const GncInt128 b) const
noexcept

Computes the Least Common Multiple between the object and parameter.

Returns
A GncInt128 having the LCM.

Definition at line 221 of file gnc-int128.cpp.

222{
223 auto common = gcd(b);
224 return *this / common * b.abs(); //Preserve our sign, discard the other's.
225}
GncInt128 gcd(GncInt128 b) const noexcept
Computes the Greatest Common Divisor between the object and parameter.

◆ operator bool()

GncInt128::operator bool ( ) const
explicitnoexcept

Definition at line 317 of file gnc-int128.cpp.

318{
319 return ! isZero ();
320}

◆ operator int64_t()

GncInt128::operator int64_t ( ) const
explicit

Explicit conversion to int64_t.

Returns
A int64_t
Exceptions
std::overflow_errorif the object's value is > INT64_MAX or NaN.
std::underflow_errorif the object's value is < INT64_MIN

Definition at line 128 of file gnc-int128.cpp.

129{
130 auto flags = get_flags(m_hi);
131 if ((flags & neg) && isBig())
132 throw std::underflow_error ("Negative value too large to represent as int64_t");
133 if ((flags & (overflow | NaN)) || isBig())
134 throw std::overflow_error ("Value too large to represent as int64_t");
135 int64_t retval = static_cast<int64_t>(m_lo);
136 return flags & neg ? -retval : retval;
137}
bool isBig() const noexcept

◆ operator uint64_t()

GncInt128::operator uint64_t ( ) const
explicit

Explicit conversion to uint64_t.

Returns
A uint64_t
Exceptions
std::overflow_errorif the object's value is > UINT64_MAX or NaN.
std::underflow_errorif the object's value is < 0.

Definition at line 139 of file gnc-int128.cpp.

140{
141 auto flags = get_flags(m_hi);
142 if ((flags & neg) && !isZero()) // exclude negative zero
143 throw std::underflow_error ("Can't represent negative value as uint64_t");
144 if ((flags & (overflow | NaN)) || (m_hi || m_lo > UINT64_MAX))
145 throw std::overflow_error ("Value to large to represent as uint64_t");
146 return m_lo;
147}

◆ operator%=()

GncInt128 & GncInt128::operator%= ( const GncInt128 b)
noexcept

Definition at line 816 of file gnc-int128.cpp.

817{
818 GncInt128 q {}, r {};
819 div(b, q, r);
820 std::swap (*this, r);
821 if (q.isNan())
822 m_hi = set_flags(m_hi, (get_flags(m_hi) | NaN));
823 return *this;
824}
void div(const GncInt128 &d, GncInt128 &q, GncInt128 &r) const noexcept
Computes a quotient and a remainder, passed as reference parameters.

◆ operator&=()

GncInt128 & GncInt128::operator&= ( const GncInt128 b)
noexcept

Definition at line 827 of file gnc-int128.cpp.

828{
829 auto flags = get_flags(m_hi);
830 if (b.isOverflow())
831 flags |= overflow;
832 if (b.isNan())
833 flags |= NaN;
834 m_hi = set_flags(m_hi, flags);
835 if (isOverflow() || isNan())
836 return *this;
837 auto hi = get_num(m_hi);
838 hi &= get_num(b.m_hi);
839 m_lo &= b.m_lo;
840 m_hi = set_flags(hi, flags);
841 return *this;
842}

◆ operator*=()

GncInt128 & GncInt128::operator*= ( const GncInt128 b)
noexcept

Definition at line 475 of file gnc-int128.cpp.

476{
477 /* Test for 0 first */
478 auto flags = get_flags(m_hi);
479 /* Handle the sign; ^ flips if b is negative */
480 flags ^= (get_flags(b.m_hi) & neg);
481 if (isZero() || b.isZero())
482 {
483 m_lo = 0;
484 m_hi = set_flags(0, flags);
485 return *this;
486 }
487 if (b.isOverflow())
488 flags |= overflow;
489 if (b.isNan())
490 flags |= NaN;
491 m_hi = set_flags(m_hi, flags);
492 if (isOverflow() || isNan())
493 return *this;
494
495 /* Test for overflow before spending time on the calculation */
496 auto hi = get_num(m_hi);
497 auto bhi = get_num(b.m_hi);
498 if (hi && bhi)
499 {
500 flags |= overflow;
501 m_hi = set_flags(hi, flags);
502 return *this;
503 }
504
505 unsigned int abits {bits()}, bbits {b.bits()};
506 /* If the product of the high bytes < 7fff then the result will have abits +
507 * bbits -1 bits and won't actually overflow. It's not worth the effort to
508 * work that out for this corner-case, so we'll take the risk and calculate
509 * the product and catch the overflow later.
510 */
511 if (abits + bbits - 1 > maxbits)
512 {
513 flags |= overflow;
514 m_hi = set_flags(m_hi, flags);
515 return *this;
516 }
517
518 /* The trivial case */
519 if (abits + bbits <= legbits)
520 {
521 m_lo *= b.m_lo;
522 m_hi = set_flags(m_hi, flags);
523 return *this;
524 }
525
526/* This is Knuth's "classical" multi-precision multiplication algorithm
527 * truncated to a GncInt128 result with the loop unrolled for clarity and with
528 * overflow and zero checks beforehand to save time. See Donald Knuth, "The Art
529 * of Computer Programming Volume 2: Seminumerical Algorithms", Addison-Wesley,
530 * 1998, p 268.
531 *
532 * There are potentially faster algorithms (O(n^1.6) instead of O(n^2) for the
533 * full precision), but this is already close to that fast because of truncation
534 * and it's not clear that the truncation is applicable to the faster
535 * algorithms.
536 */
537
538 uint64_t av[sublegs] {(m_lo & sublegmask), (m_lo >> sublegbits),
539 (hi & sublegmask), (hi >> sublegbits)};
540 uint64_t bv[sublegs] {(b.m_lo & sublegmask), (b.m_lo >> sublegbits),
541 (bhi & sublegmask), (bhi >> sublegbits)};
542 uint64_t rv[sublegs] {};
543 uint64_t carry {}, scratch {};
544
545 rv[0] = av[0] * bv[0];
546
547 rv[1] = av[1] * bv [0];
548 scratch = rv[1] + av[0] * bv[1];
549 carry = rv[1] > scratch ? 1 : 0;
550 rv[1] = scratch;
551
552 rv[2] = av[2] * bv[0] + carry; //0xffff^2 + 1 < 0xffffffff, can't overflow
553 scratch = rv[2] + av[1] * bv[1];
554 carry = rv[2] > scratch ? 1 : 0;
555 rv[2] = scratch + av[0] * bv[2];
556 carry += scratch > rv[2] ? 1 : 0;
557
558 rv[3] = av[3] * bv[0] + carry;
559 scratch = rv[3] + av[2] * bv[1];
560 carry = rv[3] > scratch ? 1 : 0;
561 rv[3] = scratch + av[1] * bv[2];
562 carry += scratch > rv[3] ? 1 : 0;
563 scratch = rv[3] + av[0] * bv[3];
564 carry += rv[3] > scratch ? 1 : 0;
565 rv[3] = scratch;
566
567 if (carry) //Shouldn't happen because of the checks above
568 {
569 flags |= overflow;
570 m_hi = set_flags(m_hi, flags);
571 return *this;
572 }
573
574 m_lo = rv[0] + (rv[1] << sublegbits);
575 carry = rv[1] >> sublegbits;
576 carry += (rv[1] << sublegbits) > m_lo || rv[0] > m_lo ? 1 : 0;
577 hi = rv[2] + (rv[3] << sublegbits) + carry;
578 if ((rv[3] << sublegbits) > hi || rv[2] > hi || (rv[3] >> sublegbits) ||
579 hi & flagmask)
580 {
581 flags |= overflow;
582 m_hi = set_flags(hi, flags);
583 return *this;
584 }
585 m_hi = set_flags(hi, flags);
586 return *this;
587}

◆ operator++() [1/2]

GncInt128 & GncInt128::operator++ ( )
noexcept

Definition at line 323 of file gnc-int128.cpp.

324{
325 return operator+=(UINT64_C(1));
326}

◆ operator++() [2/2]

GncInt128 & GncInt128::operator++ ( int  )
noexcept

Definition at line 329 of file gnc-int128.cpp.

330{
331 return operator+=(UINT64_C(1));
332}

◆ operator+=()

GncInt128 & GncInt128::operator+= ( const GncInt128 b)
noexcept

Definition at line 347 of file gnc-int128.cpp.

348{
349 auto flags = get_flags(m_hi);
350 if (b.isOverflow())
351 flags |= overflow;
352 if (b.isNan())
353 flags |= NaN;
354 m_hi = set_flags(m_hi, flags);
355 if (isOverflow() || isNan())
356 return *this;
357 if ((isNeg () && !b.isNeg ()) || (!isNeg () && b.isNeg ()))
358 return this->operator-= (-b);
359 uint64_t result = m_lo + b.m_lo;
360 uint64_t carry = static_cast<int64_t>(result < m_lo); //Wrapping
361 m_lo = result;
362 auto hi = get_num(m_hi);
363 auto bhi = get_num(b.m_hi);
364 result = hi + bhi + carry;
365 if (result < hi || result & flagmask)
366 flags |= overflow;
367 m_hi = set_flags(result, flags);
368 return *this;
369}

◆ operator-()

GncInt128 GncInt128::operator- ( ) const
noexcept

Definition at line 305 of file gnc-int128.cpp.

306{
307 auto retval = *this;
308 auto flags = get_flags(retval.m_hi);
309 if (isNeg())
310 flags ^= neg;
311 else
312 flags |= neg;
313 retval.m_hi = set_flags(retval.m_hi, flags);
314 return retval;
315}

◆ operator--() [1/2]

GncInt128 & GncInt128::operator-- ( )
noexcept

Definition at line 335 of file gnc-int128.cpp.

336{
337 return operator-=(UINT64_C(1));
338}

◆ operator--() [2/2]

GncInt128 & GncInt128::operator-- ( int  )
noexcept

Definition at line 341 of file gnc-int128.cpp.

342{
343 return operator-=(UINT64_C(1));
344}

◆ operator-=()

GncInt128 & GncInt128::operator-= ( const GncInt128 b)
noexcept

Definition at line 427 of file gnc-int128.cpp.

428{
429 auto flags = get_flags(m_hi);
430 if (b.isOverflow())
431 flags |= overflow;
432 if (b.isNan())
433 flags |= NaN;
434 m_hi = set_flags(m_hi, flags);
435
436 if (isOverflow() || isNan())
437 return *this;
438
439 if ((!isNeg() && b.isNeg()) || (isNeg() && !b.isNeg()))
440 return this->operator+= (-b);
441 bool operand_bigger {abs().cmp (b.abs()) < 0};
442 auto hi = get_num(m_hi);
443 auto far_hi = get_num(b.m_hi);
444 if (operand_bigger)
445 {
446 flags ^= neg; // ^= flips the bit
447 if (m_lo > b.m_lo)
448 {
449 /* The + 1 on the end is because we really want to use 2^64, or
450 * UINT64_MAX + 1, but that can't be represented in a uint64_t.
451 */
452 m_lo = UINT64_MAX - m_lo + b.m_lo + 1;
453 --far_hi; //borrow
454 }
455 else
456 m_lo = b.m_lo - m_lo;
457 hi = far_hi - hi;
458 m_hi = set_flags(hi, flags);
459 return *this;
460 }
461 if (m_lo < b.m_lo)
462 {
463 m_lo = UINT64_MAX - b.m_lo + m_lo + 1; //See UINT64_MAX comment above
464 --hi; //borrow
465 }
466 else
467 m_lo -= b.m_lo;
468
469 hi -= far_hi;
470 m_hi = set_flags(hi, flags);
471 return *this;
472}
int cmp(const GncInt128 &b) const noexcept
Compare function.

◆ operator/=()

GncInt128 & GncInt128::operator/= ( const GncInt128 b)
noexcept

Definition at line 807 of file gnc-int128.cpp.

808{
809 GncInt128 q {}, r {};
810 div(b, q, r);
811 std::swap (*this, q);
812 return *this;
813}

◆ operator<<=()

GncInt128 & GncInt128::operator<<= ( unsigned int  i)
noexcept

Definition at line 371 of file gnc-int128.cpp.

373{
374 auto flags = get_flags(m_hi);
375 if (i == 0)
376 return *this;
377 if (i > maxbits)
378 {
379 flags &= 0xfe;
380 m_hi = set_flags(0, flags);
381 m_lo = 0;
382 return *this;
383 }
384 auto hi = get_num(m_hi);
385 if (i < legbits)
386 {
387 uint64_t carry {(m_lo & (((UINT64_C(1) << i) - 1) << (legbits - i))) >> (legbits - i)};
388 m_lo <<= i;
389 hi <<= i;
390 hi += carry;
391 m_hi = set_flags(hi, flags);
392 return *this;
393 }
394 hi = m_lo << (i - legbits);
395 m_hi = set_flags(hi, flags);
396 m_lo = 0;
397 return *this;
398}

◆ operator>>=()

GncInt128 & GncInt128::operator>>= ( unsigned int  i)
noexcept

Definition at line 401 of file gnc-int128.cpp.

402{
403 auto flags = get_flags(m_hi);
404 if (i > maxbits)
405 {
406 flags &= 0xfe;
407 m_hi = set_flags(0, flags);
408 m_lo = 0;
409 return *this;
410 }
411 auto hi = get_num(m_hi);
412 if (i < legbits)
413 {
414 uint64_t carry {(hi & ((UINT64_C(1) << i) - 1))};
415 m_lo >>= i;
416 hi >>= i;
417 m_lo += (carry << (legbits - i));
418 m_hi = set_flags(hi, flags);
419 return *this;
420 }
421 m_lo = hi >> (i - legbits);
422 m_hi = set_flags(0, flags);
423 return *this;
424}

◆ operator^=()

GncInt128 & GncInt128::operator^= ( const GncInt128 b)
noexcept

Definition at line 856 of file gnc-int128.cpp.

857{
858 auto flags = get_flags(m_hi);
859 if (b.isOverflow())
860 flags |= overflow;
861 if (b.isNan())
862 flags |= NaN;
863 m_hi = set_flags(m_hi, flags);
864 if (isOverflow() || isNan())
865 return *this;
866 auto hi = get_num(m_hi);
867 hi ^= get_num(b.m_hi);
868 m_hi = set_flags(hi, flags);
869 m_lo ^= b.m_lo;
870 return *this;
871}

◆ operator|=()

GncInt128 & GncInt128::operator|= ( const GncInt128 b)
noexcept

Definition at line 845 of file gnc-int128.cpp.

846{
847 auto flags = get_flags(m_hi);
848 auto hi = get_num(m_hi);
849 hi ^= get_num(b.m_hi);
850 m_hi = set_flags(hi, flags);
851 m_lo ^= b.m_lo;
852 return *this;
853}

◆ pow()

GncInt128 GncInt128::pow ( unsigned int  n) const
noexcept

Computes the object raised to the parameter's power.

Parameters
bThe power to raise this to. No point in taking a GncInt128, any value greater than 128 would overflow on any value other than 1.
Returns
A GncInt128

Definition at line 229 of file gnc-int128.cpp.

230{
231 if (isZero() || (m_lo == 1 && m_hi == 0) || isNan() || isOverflow())
232 return *this;
233 if (b == 0)
234 return GncInt128 (1);
235 GncInt128 retval (1), squares = *this;
236 while (b && !retval.isOverflow())
237 {
238 if (b & 1)
239 retval *= squares;
240 squares *= squares;
241 b >>= 1;
242 }
243 return retval;
244}

◆ valid()

bool GncInt128::valid ( ) const
noexcept
Returns
true if neither the overflow nor nan flags are set.

Definition at line 271 of file gnc-int128.cpp.

272{
273 return !(get_flags(m_hi) & (overflow | NaN));
274}

◆ zero()

GncInt128 & GncInt128::zero ( )
noexcept

Clear the object.

Sets all member variables to zero.

Returns
A reference to the object for chaining.

Definition at line 122 of file gnc-int128.cpp.

123{
124 m_lo = m_hi = UINT64_C(0);
125 return *this;
126}

Field Documentation

◆ flagbits

const unsigned int GncInt128::flagbits = 3
static

Definition at line 67 of file gnc-int128.hpp.

◆ legbits

const unsigned int GncInt128::legbits = 64
static

Definition at line 69 of file gnc-int128.hpp.

◆ maxbits

const unsigned int GncInt128::maxbits = legbits * numlegs - flagbits
static

Definition at line 70 of file gnc-int128.hpp.

◆ numlegs

const unsigned int GncInt128::numlegs = 2
static

Definition at line 68 of file gnc-int128.hpp.


The documentation for this class was generated from the following files: