GnuCash  4.12-527-g05ffd3d4eb
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. More...
 
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. More...
 
int cmp (const GncInt128 &b) const noexcept
 Compare function. More...
 
GncInt128 gcd (GncInt128 b) const noexcept
 Computes the Greatest Common Divisor between the object and parameter. More...
 
GncInt128 lcm (const GncInt128 &b) const noexcept
 Computes the Least Common Multiple between the object and parameter. More...
 
GncInt128 pow (unsigned int n) const noexcept
 Computes the object raised to the parameter's power. More...
 
void div (const GncInt128 &d, GncInt128 &q, GncInt128 &r) const noexcept
 Computes a quotient and a remainder, passed as reference parameters. More...
 
 operator int64_t () const
 Explicit conversion to int64_t. More...
 
 operator uint64_t () const
 Explicit conversion to uint64_t. More...
 
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) const noexcept
 Fills a supplied buffer with a representation of the number in base 10. More...
 
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 64 of file gnc-int128.hpp.

Member Function Documentation

◆ asCharBufR()

char * GncInt128::asCharBufR ( char *  buf) 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 922 of file gnc-int128.cpp.

923 {
924  if (isOverflow())
925  {
926  sprintf (buf, "%s", "Overflow");
927  return buf;
928  }
929  if (isNan())
930  {
931  sprintf (buf, "%s", "NaN");
932  return buf;
933  }
934  if (isZero())
935  {
936  sprintf (buf, "%d", 0);
937  return buf;
938  }
939  uint64_t d[dec_array_size] {};
940  decimal_from_binary(d, get_num(m_hi), m_lo);
941  char* next = buf;
942  char neg {'-'};
943 
944  if (isNeg()) *(next++) = neg;
945  bool trailing {false};
946  for (unsigned int i {dec_array_size}; i; --i)
947  if (d[i - 1] || trailing)
948  {
949  if (trailing)
950  next += sprintf (next, "%8.8" PRIu64, d[i - 1]);
951  else
952  next += sprintf (next, "%" PRIu64, d[i - 1]);
953 
954  trailing = true;
955  }
956 
957  return buf;
958 }
bool isNan() const noexcept
Definition: gnc-int128.cpp:268
bool isZero() const noexcept
Definition: gnc-int128.cpp:280
bool isNeg() const noexcept
Definition: gnc-int128.cpp:250
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:262

◆ bits()

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

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

297 {
298  auto hi = get_num(m_hi);
299  unsigned int bits {static_cast<unsigned int>(hi == 0 ? 0 : 64)};
300  uint64_t temp {(hi == 0 ? m_lo : hi)};
301  for (;temp > 0; temp >>= 1)
302  ++bits;
303  return bits;
304 }
unsigned int bits() const noexcept
Definition: gnc-int128.cpp:296

◆ 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 154 of file gnc-int128.cpp.

155 {
156  auto flags = get_flags(m_hi);
157  if (flags & (overflow | NaN))
158  return -1;
159  if (b.isOverflow () || b.isNan ())
160  return 1;
161  auto hi = get_num(m_hi);
162  auto bhi = get_num(b.m_hi);
163  if (isZero() && b.isZero()) return 0;
164  if (flags & neg)
165  {
166  if (!b.isNeg()) return -1;
167  if (hi > bhi) return -1;
168  if (hi < bhi) return 1;
169  if (m_lo > b.m_lo) return -1;
170  if (m_lo < b.m_lo) return 1;
171  return 0;
172  }
173  if (b.isNeg()) return 1;
174  if (hi < bhi) return -1;
175  if (hi > bhi) return 1;
176  if (m_lo < b.m_lo) return -1;
177  if (m_lo > b.m_lo) return 1;
178  return 0;
179 }
bool isNan() const noexcept
Definition: gnc-int128.cpp:268
bool isZero() const noexcept
Definition: gnc-int128.cpp:280
bool isNeg() const noexcept
Definition: gnc-int128.cpp:250
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:262

◆ 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 727 of file gnc-int128.cpp.

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

◆ 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 185 of file gnc-int128.cpp.

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

◆ isBig()

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

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

257 {
258  return (get_num(m_hi) || m_lo > INT64_MAX);
259 }

◆ isNan()

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

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

269 {
270  return (get_flags(m_hi) & NaN);
271 }

◆ isNeg()

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

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

251 {
252  return (get_flags(m_hi) & neg);
253 }

◆ 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 262 of file gnc-int128.cpp.

263 {
264  return (get_flags(m_hi) & overflow);
265 }

◆ isZero()

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

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

281 {
282  return ((get_flags(m_hi) & (overflow | NaN)) == 0 &&
283  get_num(m_hi) == 0 && m_lo == 0);
284 }

◆ 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 224 of file gnc-int128.cpp.

225 {
226  auto common = gcd(b);
227  return *this / common * b.abs(); //Preserve our sign, discard the other's.
228 }
GncInt128 gcd(GncInt128 b) const noexcept
Computes the Greatest Common Divisor between the object and parameter.
Definition: gnc-int128.cpp:185

◆ 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 131 of file gnc-int128.cpp.

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

◆ 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 142 of file gnc-int128.cpp.

143 {
144  auto flags = get_flags(m_hi);
145  if ((flags & neg) && !isZero()) // exclude negative zero
146  throw std::underflow_error ("Can't represent negative value as uint64_t");
147  if ((flags & (overflow | NaN)) || (m_hi || m_lo > UINT64_MAX))
148  throw std::overflow_error ("Value to large to represent as uint64_t");
149  return m_lo;
150 }
bool isZero() const noexcept
Definition: gnc-int128.cpp:280

◆ 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 232 of file gnc-int128.cpp.

233 {
234  if (isZero() || (m_lo == 1 && m_hi == 0) || isNan() || isOverflow())
235  return *this;
236  if (b == 0)
237  return GncInt128 (1);
238  GncInt128 retval (1), squares = *this;
239  while (b && !retval.isOverflow())
240  {
241  if (b & 1)
242  retval *= squares;
243  squares *= squares;
244  b >>= 1;
245  }
246  return retval;
247 }
GncInt128()
Default constructor.
Definition: gnc-int128.cpp:67
bool isNan() const noexcept
Definition: gnc-int128.cpp:268
bool isZero() const noexcept
Definition: gnc-int128.cpp:280
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:262

◆ valid()

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

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

275 {
276  return !(get_flags(m_hi) & (overflow | NaN));
277 }

◆ 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 125 of file gnc-int128.cpp.

126 {
127  m_lo = m_hi = UINT64_C(0);
128  return *this;
129 }

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