GnuCash  5.6-150-g038405b370+
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, uint32_t size) 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 61 of file gnc-int128.hpp.

Member Function Documentation

◆ 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 isNan() const noexcept
Definition: gnc-int128.cpp:265
bool isZero() const noexcept
Definition: gnc-int128.cpp:277
bool isNeg() const noexcept
Definition: gnc-int128.cpp:247
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:259

◆ 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
Definition: gnc-int128.cpp:293

◆ 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 }
bool isNan() const noexcept
Definition: gnc-int128.cpp:265
bool isZero() const noexcept
Definition: gnc-int128.cpp:277
bool isNeg() const noexcept
Definition: gnc-int128.cpp:247
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:259

◆ 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()
Default constructor.
Definition: gnc-int128.cpp:64
bool isNan() const noexcept
Definition: gnc-int128.cpp:265
bool isNeg() const noexcept
Definition: gnc-int128.cpp:247
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:259
GncInt128 & zero() noexcept
Clear the object.
Definition: gnc-int128.cpp:122

◆ 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 }
bool isNan() const noexcept
Definition: gnc-int128.cpp:265
bool isZero() const noexcept
Definition: gnc-int128.cpp:277
bool isNeg() const noexcept
Definition: gnc-int128.cpp:247
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:259

◆ 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.
Definition: gnc-int128.cpp:182

◆ 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
Definition: gnc-int128.cpp:253

◆ 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 }
bool isZero() const noexcept
Definition: gnc-int128.cpp:277

◆ 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 }
GncInt128()
Default constructor.
Definition: gnc-int128.cpp:64
bool isNan() const noexcept
Definition: gnc-int128.cpp:265
bool isZero() const noexcept
Definition: gnc-int128.cpp:277
bool isOverflow() const noexcept
Definition: gnc-int128.cpp:259

◆ 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 }

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