Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cBigInteger.h
Go to the documentation of this file.
1 //
4 //
5 #ifndef _INC_cBigInteger_H
6 #define _INC_cBigInteger_H
7 #ifndef NO_PRAGMA_ONCE
8 #pragma once
9 #endif
10 
11 #include "cBigUnsigned.h"
12 
13 namespace GrayLib
14 {
16 
18  {
24 
25  typedef cBigUnsigned SUPER_t;
26  typedef cBigInteger THIS_t;
27 
28  private:
29  bool m_bNegative;
30 
31  public:
33  : m_bNegative(false)
34  {
36  }
37  cBigInteger(const THIS_t& x)
38  : SUPER_t(x)
39  , m_bNegative(x.m_bNegative)
40  {
42  }
43  cBigInteger(const cBigUnsigned& x, bool bNegative = false)
44  : SUPER_t(x)
45  , m_bNegative(bNegative)
46  {
48  CheckNegativeZero();
49  }
50  cBigInteger(const char* pszStr, RADIX_t uRadix = 10)
51  : m_bNegative(false)
52  {
54  SetStr(pszStr, uRadix);
55  }
56 
57  cBigInteger(BLOCK_ENUM_t nBlocks, const BLOCK_t* pBlocks, bool bNegative)
58  : SUPER_t(nBlocks, pBlocks)
59  , m_bNegative(bNegative)
60  {
62  ASSERT(!isStatic());
63  }
64  cBigInteger(BLOCK_ENUM_t nBlocks, const BLOCK_t* pBlocks, bool bStatic, bool bNegative)
65  : SUPER_t(nBlocks, pBlocks, bStatic)
66  , m_bNegative(bNegative)
67  {
69  ASSERT(isStatic());
70  }
71 
72  // Constructors from primitive integer types
73  cBigInteger(UINTMAX_t x) { put_ValU(x); }
74  cBigInteger(INTMAX_t x) { put_ValS(x); }
75 #if 1 // Stupid C++ compiler wont pick the correct one.
76  cBigInteger(UINT32 x) { put_ValU(x); }
77  cBigInteger(INT32 x) { put_ValS(x); }
78 #endif
79 
80  // Accessors
81  bool isNegative() const
82  {
83  ASSERT(!m_bNegative || !isZero());
84  return m_bNegative;
85  }
86  int get_Sign() const
87  {
88  ASSERT(!m_bNegative || !isZero());
89  return m_bNegative ? (-1) : 1;
90  }
91  const cBigUnsigned& get_Magnitude() const
92  {
94  return *this;
95  }
96 
97  // Compares this to x like Perl's <=>
99  {
100  if (isNegative())
101  return COMPARE_Less;
102  return SUPER_t::CompareU(x);
103  }
104  COMPARE_t CompareS(BLOCKI_t x) const;
105  COMPARE_t Compare(const cBigInteger& x) const;
107  {
109  return SUPER_t::Compare(x);
110  }
111 
112  bool IsEqual(const THIS_t& x) const
113  {
114  return (m_bNegative == x.m_bNegative) && get_Magnitude().IsEqual(x.get_Magnitude());
115  }
116  bool IsEqual(BLOCKI_t x) const
117  {
118  // AKA IsEqualS ?
119  if (get_BlocksUse() > 1)
120  return false;
121  BLOCK_t ux;
122  if (x < 0)
123  {
124  if (!m_bNegative)
125  return false;
126  ux = (BLOCK_t)-x;
127  }
128  else
129  {
130  if (m_bNegative)
131  return false;
132  ux = (BLOCK_t)x;
133  }
134  return GetBlock(0) == ux;
135  }
136 
137  // Ordinary comparison operators
138  bool operator ==(const THIS_t& x) const
139  {
140  return IsEqual(x);
141  }
142  bool operator !=(const THIS_t& x) const
143  {
144  return !IsEqual(x);
145  }
146  bool operator < (const THIS_t& x) const
147  {
148  return Compare(x) < 0;
149  }
150  bool operator <=(const THIS_t& x) const
151  {
152  return Compare(x) <= 0;
153  }
154  bool operator >=(const THIS_t& x) const
155  {
156  return Compare(x) >= 0;
157  }
158  bool operator > (const THIS_t& x) const
159  {
160  return Compare(x) > 0;
161  }
162 
163  template <typename TYPE /*= BLOCK_t*/>
164  TYPE get_ValS() const
165  {
167  TYPE nVal = SUPER_t::get_ValS<TYPE>();
168  if (m_bNegative)
169  nVal = -nVal;
170  return nVal;
171  }
172  template <typename TYPE /*= BLOCK_t*/>
173  TYPE get_Val() const
174  {
176  return SUPER_t::get_ValUC<TYPE>();
177  }
178 
179  StrLen_t GetStr(char* pszOut, StrLen_t iOutMax, RADIX_t uRadix = 10) const;
180  cString GetStr(RADIX_t uRadix = 10) const;
181 
182  // Modifiers
183  bool SetStr(const char* pszIn, RADIX_t uRadix = 10, const char** ppszEnd = nullptr);
184 
185  HRESULT SetBinaryBE(const BYTE* pData, size_t nSize, bool bByteSign);
186  HRESULT SetBinaryBE(const cMemBlock& b, bool bByteSign)
187  {
188  return SetBinaryBE(b.get_DataBytes(), b.get_DataSize(), bByteSign);
189  }
190 
191  HRESULT GetBinaryBE(BYTE* pOut, size_t nSizeOut) const
192  {
193  ASSERT(!isNegative());
194  return SUPER_t::GetBinaryBE(pOut, nSizeOut);
195  }
196 
197  void SetCopyInt(const cBigInteger& x);
198 
199  HRESULT SetCopySecure(const THIS_t& val, bool assign)
200  {
201  HRESULT hRes = SUPER_t::SetCopySecure(val, assign);
202  this->put_Sign(this->get_Sign() * (1 - assign) + val.get_Sign() * assign);
203  return hRes;
204  }
205  static HRESULT GRAYCALL SwapSecure(THIS_t& X, THIS_t& Y, bool swap) // static
206  {
207  HRESULT hRes = SUPER_t::SwapSecure(X, Y, swap);
208  int s = X.get_Sign();
209  X.put_Sign(X.get_Sign() * (1 - swap) + Y.get_Sign() * swap);
210  Y.put_Sign(Y.get_Sign() * (1 - swap) + s * swap);
211  return hRes;
212  }
213 
214  void operator=(const THIS_t& x)
215  {
216  SetCopyInt(x);
217  }
218 
219  void SetZeroAll()
220  {
221  m_bNegative = false;
222  SUPER_t::SetZeroAll();
223  }
224  void SetNullVal()
225  {
226  m_bNegative = false;
227  SUPER_t::SetNullVal();
228  }
229 
231  {
233  m_bNegative = false;
234  SUPER_t::put_ValU(n);
235  }
237  {
238  m_bNegative = (n < 0);
239  SUPER_t::put_ValU((UINTMAX_t)(m_bNegative ? (-n) : n));
240  }
241  template <typename TYPE>
242  void put_Val(TYPE n)
243  {
245  return put_ValU(n);
246  }
247 
248  void SetBlocksStatic(BLOCK_ENUM_t nBlocks, const BLOCK_t* pBlocks);
249  void SetBlocksStatic(const cBitArrayStatic& b);
250 
251  // OPERATORS -- See the discussion in cBigUnsigned.hh.
252  void OpAdd1(BLOCKI_t n);
253  void OpSubtract1(BLOCKI_t n);
254 
255  void InitAdd(const cBigInteger& a, const cBigInteger& b);
256  void InitAddU(const cBigUnsigned& a, const cBigUnsigned& b)
257  {
259  this->put_Negative(false);
260  SUPER_t::InitAdd(a, b);
261  }
262  void InitSubtract(const cBigInteger& a, const cBigInteger& b);
264  {
266  this->put_Negative(false);
267  return SUPER_t::InitSubtract(a, b);
268  }
269  void OpSubtract(const THIS_t& b)
270  {
271  InitSubtract(*this, b);
272  }
274  {
275  return SUPER_t::OpSubtract(a);
276  }
277 
278  void InitSubtract1(const THIS_t& a, BLOCKI_t n)
279  {
280  if (this != &a)
281  SetCopyInt(a);
282  OpSubtract1(n);
283  }
284  void InitAdd1(const THIS_t& a, BLOCKI_t n)
285  {
286  if (this != &a)
287  SetCopyInt(a);
288  OpAdd1(n);
289  }
290 
291  void InitMultiply(const cBigInteger& a, const cBigInteger& b);
292  HRESULT InitDivide(const cBigInteger& dividend, const cBigInteger& divisor, OUT cBigInteger& remainder);
293  HRESULT InitDivide(const THIS_t& a, const cBigInteger& b)
294  {
296  THIS_t rJunkRemainder;
297  return InitDivide(a, b, rJunkRemainder);
298  }
299  HRESULT InitModulus(const THIS_t& a, const THIS_t& b)
300  {
302  THIS_t rJunkQuotient;
303  return rJunkQuotient.InitDivide(a, b, *this);
304  }
305  HRESULT InitModulusU(const THIS_t& a, const THIS_t& b);
306 
308  {
309  BLOCK_t nVal = SUPER_t::GetModulusH(b);
310  // If this is negative, then the current nVal represents a negative value.
311  // Flipping it to the positive side.
312  if (this->isNegative() && nVal != 0)
313  nVal = b - nVal;
314  return nVal;
315  }
316 
317  cBigInteger operator +(const THIS_t& x) const
318  {
319  cBigInteger ans;
320  ans.InitAdd(*this, x);
321  return ans;
322  }
323  cBigInteger operator -(const THIS_t& x) const
324  {
325  cBigInteger ans;
326  ans.InitSubtract(*this, x);
327  return ans;
328  }
329  cBigInteger operator *(const THIS_t& x) const
330  {
331  cBigInteger ans;
332  ans.InitMultiply(*this, x);
333  return ans;
334  }
335  cBigInteger operator /(const THIS_t& x) const
336  {
337  cBigInteger q;
338  q.InitDivide(*this, x);
339  return q;
340  }
341  cBigInteger operator %(const THIS_t& x) const
342  {
344  cBigInteger r;
345  r.InitModulus(*this, x);
346  return r;
347  }
348  cBigInteger operator -() const
349  {
350  cBigInteger ans;
351  ans.SetCopyInt(*this);
352  ans.FlipSign();
353  return ans;
354  }
355 
356  void operator +=(const THIS_t& x)
357  {
358  InitAdd(*this, x);
359  }
360  void operator -=(const THIS_t& x)
361  {
362  InitSubtract(*this, x);
363  }
364  void operator *=(const THIS_t& x)
365  {
366  InitMultiply(*this, x);
367  }
368  void operator /=(const THIS_t& x)
369  {
371  cBigInteger d = *this;
372  InitDivide(d, x);
373  }
374  inline void operator %=(const THIS_t& x)
375  {
377  cBigInteger d = *this;
378  InitModulus(d, x);
379  }
380 
382  {
384  if (m_bNegative && isZero())
385  m_bNegative = false;
386  }
387  void put_Negative(bool b = true)
388  {
390  m_bNegative = b;
391  CheckNegativeZero();
392  }
393  void put_Sign(int nSign)
394  {
396  m_bNegative = (nSign < 0);
397  CheckNegativeZero();
398  }
399  inline void FlipSign()
400  {
402  if (isZero())
403  {
404  m_bNegative = false;
405  return;
406  }
407  m_bNegative = !m_bNegative;
408  }
409 
410  // INCREMENT/DECREMENT OPERATORS
411  void operator ++()
412  {
413  OpAdd1(1);
414  }
415  void operator ++(int)
416  {
417  OpAdd1(1);
418  }
419  void operator --()
420  {
421  OpSubtract1(1);
422  }
423  void operator --(int)
424  {
425  OpSubtract1(1);
426  }
427 
428  void InitGreatestCommonDivisor(const cBigInteger& a, const cBigInteger& b);
429  static HRESULT GRAYCALL ExtendedEuclidean(const cBigUnsigned& m, const cBigUnsigned& n, cBigUnsigned& g, cBigInteger& r, cBigInteger& s);
430  HRESULT InitModInv(const cBigInteger& A, const cBigInteger& N);
431  HRESULT SetPowerMod(const THIS_t& base, const THIS_t& exponent, const THIS_t& modulus, OUT cBigUnsigned* pRR);
432 
434  };
435 
436  // overloads to get signed value correctly.
437  template <> inline INT64 cBigInteger::get_Val() const
438  {
439  return get_ValS<INT64>();
440  }
441 #ifndef USE_LONG_AS_INT64
442  template <> inline long cBigInteger::get_Val() const
443  {
444  return get_ValS<long>();
445  }
446 #endif
447  template <> inline int cBigInteger::get_Val() const
448  {
449  return get_ValS<int>();
450  }
451  template <> inline short cBigInteger::get_Val() const
452  {
453  return get_ValS<short>();
454  }
455 
456 #ifdef USE_INT64
457  template <> inline void cBigInteger::put_Val(INT64 n)
458  {
459  put_ValS(n);
460  }
461 #endif
462 #ifndef USE_LONG_AS_INT64
463  template <> inline void cBigInteger::put_Val(long n)
464  {
465  put_ValS(n);
466  }
467 #endif
468  template <> inline void cBigInteger::put_Val(int n)
469  {
470  put_ValS(n);
471  }
472  template <> inline void cBigInteger::put_Val(short n)
473  {
474  put_ValS(n);
475  }
476 };
477 #endif
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
Using X files without the sources and the makefile How to use you just create a debug directory e g
Definition: Readme.txt:21
#define TYPE
Definition: StrT.cpp:38
UINT64 UINTMAX_t
Definition: SysTypes.h:435
INT64 INTMAX_t
Definition: SysTypes.h:434
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
#define ASSERT(exp)
Definition: cDebugAssert.h:87
Definition: cBigInteger.h:18
cBigInteger(INTMAX_t x)
Definition: cBigInteger.h:74
BLOCK_t GetModulusH(BLOCKH_t b) const
Definition: cBigInteger.h:307
cBigInteger(const THIS_t &x)
Definition: cBigInteger.h:37
COMPARE_t CompareU(BLOCK_t x) const
Definition: cBigInteger.h:98
void put_Negative(bool b=true)
Definition: cBigInteger.h:387
void put_Val(TYPE n)
Definition: cBigInteger.h:242
bool isNegative() const
Definition: cBigInteger.h:81
HRESULT InitDivide(const THIS_t &a, const cBigInteger &b)
Definition: cBigInteger.h:293
TYPE get_ValS() const
Definition: cBigInteger.h:164
void OpSubtract(const THIS_t &b)
Definition: cBigInteger.h:269
const cBigUnsigned & get_Magnitude() const
Definition: cBigInteger.h:91
COMPARE_t CompareMagnitude(const cBigUnsigned &x) const
Definition: cBigInteger.h:106
cBigInteger(BLOCK_ENUM_t nBlocks, const BLOCK_t *pBlocks, bool bStatic, bool bNegative)
Definition: cBigInteger.h:64
cBigInteger(const cBigUnsigned &x, bool bNegative=false)
Definition: cBigInteger.h:43
void InitAdd1(const THIS_t &a, BLOCKI_t n)
Definition: cBigInteger.h:284
HRESULT InitModulus(const THIS_t &a, const THIS_t &b)
Definition: cBigInteger.h:299
void SetNullVal()
Definition: cBigInteger.h:224
HRESULT GetBinaryBE(BYTE *pOut, size_t nSizeOut) const
Definition: cBigInteger.h:191
TYPE get_Val() const
Definition: cBigInteger.h:173
void InitSubtract1(const THIS_t &a, BLOCKI_t n)
Definition: cBigInteger.h:278
void SetCopyInt(const cBigInteger &x)
Definition: cBigInteger.cpp:173
void FlipSign()
Definition: cBigInteger.h:399
cBigInteger(const char *pszStr, RADIX_t uRadix=10)
Definition: cBigInteger.h:50
static HRESULT GRAYCALL SwapSecure(THIS_t &X, THIS_t &Y, bool swap)
Definition: cBigInteger.h:205
cBigInteger()
Definition: cBigInteger.h:32
void put_ValU(UINTMAX_t n)
Definition: cBigInteger.h:230
void operator=(const THIS_t &x)
Definition: cBigInteger.h:214
HRESULT OpSubtractU(const cBigUnsigned &a)
Definition: cBigInteger.h:273
void put_Sign(int nSign)
Definition: cBigInteger.h:393
bool IsEqual(const THIS_t &x) const
Definition: cBigInteger.h:112
bool IsEqual(BLOCKI_t x) const
Definition: cBigInteger.h:116
void put_ValS(INTMAX_t n)
Definition: cBigInteger.h:236
void CheckNegativeZero()
Definition: cBigInteger.h:381
HRESULT SetCopySecure(const THIS_t &val, bool assign)
Definition: cBigInteger.h:199
HRESULT InitSubU(const cBigUnsigned &a, const cBigUnsigned &b)
Definition: cBigInteger.h:263
HRESULT InitDivide(const cBigInteger &dividend, const cBigInteger &divisor, OUT cBigInteger &remainder)
Definition: cBigInteger.cpp:302
void SetZeroAll()
Definition: cBigInteger.h:219
cBigInteger(UINTMAX_t x)
Definition: cBigInteger.h:73
void InitSubtract(const cBigInteger &a, const cBigInteger &b)
Definition: cBigInteger.cpp:235
int get_Sign() const
Definition: cBigInteger.h:86
cBigInteger(UINT32 x)
Definition: cBigInteger.h:76
void InitAddU(const cBigUnsigned &a, const cBigUnsigned &b)
Definition: cBigInteger.h:256
cBigInteger(INT32 x)
Definition: cBigInteger.h:77
void InitMultiply(const cBigInteger &a, const cBigInteger &b)
Definition: cBigInteger.cpp:286
cBigInteger(BLOCK_ENUM_t nBlocks, const BLOCK_t *pBlocks, bool bNegative)
Definition: cBigInteger.h:57
void InitAdd(const cBigInteger &a, const cBigInteger &b)
Definition: cBigInteger.cpp:186
HRESULT SetBinaryBE(const cMemBlock &b, bool bByteSign)
Definition: cBigInteger.h:186
UNITTEST_FRIEND(cBigInteger)
Definition: cBigUnsigned.h:22
Definition: cBitArray.h:28
unsigned int BLOCK_ENUM_t
Type for the index of a BLOCK_t in the array. NOT bits BIT_ENUM_t.
Definition: cBitArray.h:78
INT32 BLOCKI_t
The biggest signed type I can do atomic math on.
Definition: cBitArray.h:47
UINT32 BLOCK_t
The biggest unsigned type I can do atomic math on for this architecture.
Definition: cBitArray.h:46
WORD BLOCKH_t
half sized BLOCK_t for multiplication overflows.
Definition: cBitArray.h:48
Definition: cMem.h:311
BYTE * get_DataBytes() const noexcept
Definition: cMem.h:354
size_t get_DataSize() const noexcept
Definition: cMem.h:344
Definition: cMesh.h:22
cVecT2< TYPE > operator*(const TYPE nVal, const cVecT2< TYPE > &v2)
Definition: cVecT.h:522
UNITTEST2_PREDEF(cQuadtree)
int COMPARE_t
result of compare. 0=same, 1=a>b, -1=a<b
Definition: cValT.h:17
int StrLen_t
the length of a string in chars (bytes for UTF8, wchar_t for UNICODE). or offset in characters....
Definition: StrConst.h:32
WORD RADIX_t
Base for convert of numbers to strings. e.g. 10 base vs 16 base hex numbers.
Definition: StrChar.h:27
bool operator<(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:234
bool operator>=(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:246
cStringA operator+(const char *pStr1, const cStringA &s2)
Definition: cString.h:642
bool operator!=(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:254
bool operator==(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:250
bool operator>(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:242
@ COMPARE_Less
VARCMP_LT.
Definition: cValT.h:22
bool operator<=(const cTimeDouble &dt1, const cTimeDouble &dt2)
Definition: cTimeDouble.h:238