Cayley
Pseudo-Random Bits from Finite Groups
uintx_t.cpp
Go to the documentation of this file.
1 
4 #include "uintx_t.h"
5 
6 #include "Includes.h"
7 
8 const int HalfBytesInWord = 2*sizeof(uint32_t);
9 const int BitsInHalfByte = 4;
10 const int BitsInWord = 8*sizeof(uint32_t);
11 
13 //Constructors and destructors.
14 
15 #pragma region structors
16 
18 
19 uintx_t::uintx_t():m_nSize(0), m_pData(nullptr){
20 } //void constructor
21 
24 
25 uintx_t::uintx_t(int i): m_nSize(1){
26  m_pData = new uint32_t[1];
27  m_pData[0] = i;
28 } //integer constructor
29 
32 
33 uintx_t::uintx_t(const char *string){
34  const int n = strlen(string);
35  m_nSize = (int)std::ceil((double)n/HalfBytesInWord);
36  m_pData = new uint32_t[m_nSize]; //grab space
37 
38  for(int i=0; i<m_nSize; i++)
39  m_pData[i] = 0; //clear m_pData
40 
41  loadstring(string); //load string
42 } //string constructor
43 
47 
49  m_nSize = x.m_nSize;
50  m_pData = new uint32_t[m_nSize]; //grab space
51 
52  for(int i=0; i<m_nSize; i++)
53  m_pData[i] = x.m_pData[i]; //load m_pData
54 } //copy constructor
55 
57 
59  delete [] m_pData;
60 } //destructor
61 
62 #pragma endregion structors
63 
65 // General purpose functions.
66 
67 #pragma region general
68 
71 
72 std::string uintx_t::GetString() const{
73  std::string s; //result
74 
75  //convert to a backwards hex string, ie. least-significant digit first
76 
77  for(int i=0; i<m_nSize; i++){ //for each word, least significant first
78  uint32_t n = m_pData[i]; //current word
79  const uint32_t size = 2*sizeof(uint32_t); //number of digits in a word
80 
81  for(auto i=0; i<size; i++){ //for each digit, least-significant first
82  uint32_t digit = n & 0xF; //grab a digit
83  char c = char(digit + (digit < 10? '0': 'A' - 10));
84  s += c; //append to string
85  n >>= 4; //next digit
86  } //while
87  } //for
88 
89  //remove leading zeros, if any
90 
91  for(auto it=std::prev(s.end()); it!=s.begin() && *it=='0';){
92  --it; //prepare for next iteration
93  s.pop_back(); //remove leading zero
94  } //while
95 
96  if(s == "")s = "0"; //safety
97 
98  //reverse the string to make it most significant digit first, and return
99 
100  std::reverse(s.begin(), s.end());
101  return s;
102 } //GetString
103 
106 
107 void uintx_t::reallocate(const int s){
108  if(m_nSize != s){ //if change needed
109  m_nSize = s;
110  delete [] m_pData;
111  m_pData = new uint32_t[s]; //get space
112 
113  for(int i=0; i<m_nSize; i++)
114  m_pData[i] = 0; //zero it out
115  } //if
116 } //reallocate
117 
120 
121 void uintx_t::grow(const int s){
122  uint32_t* olddata = m_pData; //old m_pData
123  int oldsize = m_nSize; //old m_nSize
124 
125  if(m_nSize <= s){ //if really an increase in m_nSize
126  m_pData = new uint32_t[s]; //grab new space
127  m_nSize = s;
128 
129  int i;
130 
131  for(i=0; i<oldsize; i++)
132  m_pData[i] = olddata[i]; //copy over old digits
133 
134  for(; i<m_nSize; i++)
135  m_pData[i] = 0; //zero out the rest
136 
137  delete [] olddata; //recycle old space
138  } //if
139 } //grow
140 
142 
143 uintx_t::operator uint32_t(){
144  return m_pData[0];
145 } //uint32_t
146 
149 
150 uintx_t::operator uint64_t(){
151  return (uint64_t(m_pData[1]) << 32) | m_pData[0];
152 } //uint64_t
153 
156 
158  uint32_t* olddata = m_pData; //old m_pData
159  int top;
160 
161  for(top=m_nSize - 1; top>0 && m_pData[top]==0; top--);
162 
163  if(top < m_nSize - 1){ //if really a change in m_nSize
164  m_nSize = top + 1;
165  m_pData = new uint32_t[m_nSize]; //grab new space
166 
167  for(int i=0; i<=top; i++)
168  m_pData[i] = olddata[i]; //copy over old digits
169 
170  delete [] olddata; //recycle old space
171  } //if
172 } //normalize
173 
176 
177 void uintx_t::loadstring(const char* string){
178  int i;
179  int word = m_nSize - 1; //current word in long integer
180  int digitcount = strlen(string); //number of digits in string
181 
182  int shift = (digitcount%HalfBytesInWord)*BitsInHalfByte; //shift within word
183  if(shift <= 0)shift = BitsInWord; //wrap shift amount
184 
185  for(i=0; i<m_nSize; i++)
186  m_pData[i]=0; //clear m_pData
187 
188  for(i=0; i<digitcount; i++){ //load each digit from string
189  int digit = 0;
190 
191  //convert string[i] from char to digit
192 
193  if(string[i] >= '0' && string[i] <='9')
194  digit = string[i] - '0';
195 
196  else if(string[i] >= 'A' && string[i] <= 'F')
197  digit = 10+string[i] - 'A';
198 
199  else if(string[i] >= 'a' && string[i] <= 'f')
200  digit = 10 + string[i]-'a';
201 
202  else assert(false); //safety
203 
204  //compute shift amount
205 
206  if(shift <= 0){
207  shift = BitsInWord;
208  word--;
209  } //if
210 
211  shift = shift - BitsInHalfByte;
212 
213  //load digit into word of m_pData
214 
215  m_pData[word] = m_pData[word] | (digit<<shift);
216  } //for
217 } //loadstring
218 
221 
223  if(m_nSize <= 0)return 0;
224 
225  uint32_t word = m_pData[m_nSize - 1]; //most significant word in x
226  int count = 0; //counter
227 
228  while(word > 0){
229  word >>= 1;
230  count++;
231  } //while
232 
233  return count + (m_nSize - 1)*BitsInWord;
234 } //bitcount
235 
236 #pragma endregion general
237 
239 //Assignment operators.
240 
241 #pragma region assignment
242 
246 
248  if(this != &x){ //protect against self assignment
249  reallocate(x.m_nSize); //grab enough space
250  for(int i=0; i<m_nSize; i++) //copy over data
251  m_pData[i] = x.m_pData[i];
252  } //if
253 
254  return *this;
255 } //operator=
256 
260 
262  reallocate(1);
263  *m_pData = i;
264  return *this;
265 } //operator=
266 
270 
271 uintx_t& uintx_t::operator=(const char* s){
272  const int n = (int)ceil((double)strlen(s)/HalfBytesInWord);
273  reallocate(n);
274  loadstring(s);
275  return *this;
276 } //operator=
277 
278 #pragma endregion assignment
279 
281 // Addition operators.
282 
283 #pragma region addition
284 
289 
291  return x += y;
292 } //operator+
293 
297 
299  (*this) += uintx_t(y);
300  return *this;
301 } //operator+=
302 
306 
308  uint32_t left, right, left_msb, right_msb; //operands and their msb's
309  uint32_t sum, sum_msb; //sum and its msb
310  uint32_t carry = 0; //single-bit carry
311 
312  const uint32_t mask_msb = 1 << (BitsInWord-1); //mask for most significant bit
313  const uint32_t mask_lsb = ~mask_msb; //mask for all but most significant bit
314 
315  int i; //looping variable
316  int oldsize = m_nSize;
317 
318  grow(m_nSize > y.m_nSize? m_nSize: y.m_nSize); //make enough space for result
319 
320  for(i=0; i<m_nSize; i++){ //for each word in the result
321  //grab a word from each operand
322  left = i < oldsize? m_pData[i]: 0;
323  right = i < y.m_nSize? y.m_pData[i]: 0;
324 
325  //extract the most significant bit (msb) from each
326  left_msb = (left & mask_msb) >> (BitsInWord - 1);
327  right_msb = (right & mask_msb) >> (BitsInWord - 1);
328 
329  //zero out the msb from each
330  left = left & mask_lsb;
331  right = right & mask_lsb;
332 
333  //add them
334  sum = left + right + carry;
335 
336  //compute carry
337  sum_msb = (sum & mask_msb) >> (BitsInWord - 1);
338  sum = sum & mask_lsb;
339  carry = left_msb + right_msb + sum_msb; //carry is either 0, 1, 2, or 3 here
340 
341  //put leading bit of carry back into sum
342  if((carry == 1) || (carry == 3))
343  sum = sum | mask_msb;
344 
345  m_pData[i] = sum;
346 
347  //pass along leading bit of carry
348  carry >>= 1;
349  } //for
350 
351  if(carry >= 1){ //carry of 1 fell out, need more space for result
352  grow(m_nSize + 1); //need one more place for carry
353  m_pData[m_nSize - 1] = 1; //set most significant digit
354  } //if
355 
356  return *this;
357 } //operator+=
358 
359 #pragma endregion addition
360 
362 // Comparison operators.
363 
364 #pragma region comparison
365 
370 
372  if(x.m_nSize > y.m_nSize)return true; //x>y
373  if(x.m_nSize < y.m_nSize)return false; //x<y
374 
375  //check m_pData
376  for(int i=x.m_nSize-1; i>=0; i--)
377  if(x.m_pData[i] > y.m_pData[i])return true; //x>y
378  else if(x.m_pData[i] < y.m_pData[i])return false; //x<y
379 
380  return false; //they're equal
381 } //operator>
382 
387 
388 bool operator>(uintx_t x, int y){
389  return x > uintx_t(y); //lazy way to do it
390 } //operator>
391 
396 
398  if(x.m_nSize > y.m_nSize)return true; //x>y
399  if(x.m_nSize < y.m_nSize)return false; //x<y
400 
401  //check m_pData
402  for(int i=x.m_nSize-1; i>=0; i--)
403  if(x.m_pData[i] >y .m_pData[i])return true; //x>y
404  else if(x.m_pData[i] < y.m_pData[i])return false; //x<y
405 
406  return true; //they're equal
407 } //operator>=
408 
414 
415 bool operator>=(uintx_t x, int y){
416  return x >= uintx_t(y); //lazy way to do it
417 } //operator>=
418 
423 
425  return y > x; //lazy again
426 } //operator<
427 
432 
433 bool operator<(uintx_t x, int y){
434  return x < uintx_t(y); //lazy way to do it
435 } //operator<
436 
441 
443  return y >= x; //lazy again
444 } //operator<=
445 
450 
451 bool operator<=(uintx_t x, int y){
452  return x <= uintx_t(y); //lazy way to do it
453 } //operator<=
454 
459 
461  if(x.m_nSize != y.m_nSize)
462  return false;
463 
464  //check m_pData
465  for(int i=x.m_nSize - 1; i>=0; i--)
466  if(x.m_pData[i] != y.m_pData[i])
467  return false;
468 
469  return true; //they're equal
470 } //operator==
471 
476 
477 bool operator==(uintx_t x, uint32_t y){
478  return (x.m_nSize == 1) && (x.m_pData[0] == y);
479 } //operator==
480 
485 
486 bool operator==(uint32_t x, uintx_t y){
487  return y == x;
488 } //operator==
489 
494 
496  return !(x == y);
497 } //operator!=
498 
503 
504 bool operator!=(uintx_t x, uint32_t y){
505  return !(x == y);
506 } //operator!=
507 
512 
513 bool operator!=(uint32_t x, uintx_t y){
514  return !(x == y);
515 } //operator!=
516 
517 #pragma endregion comparison
518 
520 // Bit shift operators.
521 
522 #pragma region shift
523 
527 
528 uintx_t& uintx_t::operator<<=(const int distance){
529  //grow to required m_nSize
530  if(*this > 0){
531  int oldsize = m_nSize; //save old m_nSize for later
532 
533  //compute new number of bits - divide by BitsPerWord and round up
534  grow((this->bitcount() + distance + BitsInWord - 1)/BitsInWord);
535 
536  //shift by word
537  int dest = m_nSize - 1; //copy destination
538  int src = dest - distance/BitsInWord; //copy source
539 
540  while(src >= 0){ //until end of source
541  if(src < oldsize)
542  m_pData[dest] = m_pData[src]; //copy
543  dest--; src--; //move along
544  } //while
545 
546  while(dest >= 0)
547  m_pData[dest--] = 0; //fill bottom with zeros
548 
549  //shift within words
550  const int d = distance%BitsInWord; //shift distance within words
551 
552  if(d > 0)
553  for(dest=m_nSize - 1; dest>=0; dest--){
554  m_pData[dest] <<= d;
555  if(dest > 0)
556  m_pData[dest] = m_pData[dest] | (m_pData[dest - 1] >> (BitsInWord - d));
557  } //for
558  } //if
559 
560  return *this;
561 } //operator<<=
562 
567 
569  return x <<= d;
570 } //operator<<
571 
575 
576 uintx_t& uintx_t::operator>>=(const int distance){
577  //find new size
578  int newsize = (this->bitcount() - distance + BitsInWord - 1)/BitsInWord;
579 
580  if(newsize<1)
581  *this = 0;
582 
583  else{
584  //shift by word
585  int dest = 0; //copy destination
586  int src = dest + distance/BitsInWord; //copy source
587  if(dest != src)
588  while(src < m_nSize){ //until end of source
589  m_pData[dest] = m_pData[src]; //copy
590  m_pData[src] = 0; //zero out copied word
591  dest++; src++; //move along
592  } //whilke
593 
594  //shift within words
595  const int d = distance%BitsInWord; //shift distance within words
596  if(d > 0)
597  for(dest=0; dest<newsize; dest++){
598  m_pData[dest] >>= d;
599  if(dest < m_nSize - 1)
600  m_pData[dest] = m_pData[dest] | (m_pData[dest + 1] << (BitsInWord - d));
601  } //for
602  } //else
603 
604  for(int i=newsize; i<m_nSize; i++)
605  m_pData[i] = 0; //zero out unused portion
606 
607  this->normalize(); //remove leading zero words
608 
609  return *this;
610 } //operator>>=
611 
616 
618  return x >>= d;
619 } //operator>>
620 
621 #pragma endregion shift
622 
624 // Bitwise operators.
625 
626 #pragma region bitwise
627 
632 
634  const int n = std::min(x.m_nSize, y.m_nSize);
635 
636  for(int i=0; i<n; i++)
637  x.m_pData[i] &= y.m_pData[i];
638 
639  return x;
640 } //operator|
641 
646 
647 int operator&(uintx_t x, int y){
648  return x.m_pData[0] & y;
649 } //operator&
650 
655 
657  const int n = std::min(x.m_nSize, y.m_nSize);
658 
659  for(int i=0; i<n; i++)
660  x.m_pData[i] |= y.m_pData[i];
661 
662  return x;
663 } //operator|
664 
669 
670 int operator|(uintx_t x, int y){
671  return x.m_pData[0] | y;
672 } //operator|
673 
674 #pragma endregion bitwise
675 
677 // Multiplication operators.
678 
679 #pragma region multiplication
680 
685 
687  uintx_t result(0); //place for returned result
688 
689  while(z > 0){
690  result += y * z.m_pData[0];
691  y <<= BitsInWord;
692  z >>= BitsInWord;
693  } //while
694 
695  return result;
696 } //operator*
697 
702 
704  uintx_t word, carry(0);
705 
706  word.grow(x.m_nSize);
707  carry.grow(x.m_nSize + 1);
708 
709  for(int i=0; i<x.m_nSize; i++){
710  uint64_t prod = (uint64_t)x.m_pData[i]*(uint64_t)y;
711  word.m_pData[i] = unsigned(prod & 0xFFFFFFFF);
712  carry.m_pData[i + 1] = unsigned(prod >> 32);
713  } //for
714 
715  word.normalize();
716  carry.normalize();
717 
718  return word + carry;
719 } //operator*
720 
725 
727  return y*x;
728 } //operator*
729 
734 
735 uintx_t operator*(uintx_t x, uint32_t y){
736  uintx_t word, carry(0);
737 
738  word.grow(x.m_nSize);
739  carry.grow(x.m_nSize + 1);
740 
741  for(int i=0; i<x.m_nSize; i++){
742  uint64_t prod = (uint64_t)x.m_pData[i]*(uint64_t)y;
743  word.m_pData[i] = unsigned(prod & 0xFFFFFFFF);
744  carry.m_pData[i + 1] = unsigned(prod >> 32);
745  } //for
746 
747  word.normalize();
748  carry.normalize();
749 
750  return word + carry;
751 } //operator*
752 
757 
758 uintx_t operator*(uint32_t x, uintx_t y){
759  return y*x;
760 } //operator*
761 
765 
767  return *this = *this * y;
768 } //operator*=
769 
770 #pragma endregion multiplication
771 
773 // Subtraction operators.
774 
775 #pragma region subtraction
776 
781 
783  return x -= y;
784 } //operator-
785 
789 
791  if(y >= *this)
792  *this = 0; //subtracting something too big
793 
794  else if(y > 0){
795  uint32_t left, right; //operands
796  bool borrow = false; //single-bit borrow
797  int i; //looping variable
798 
799  for(i=0; i<m_nSize; i++){ //for each word in the result
800  //grab a word from each operand
801  left=m_pData[i];
802  right = (i < y.m_nSize)? y.m_pData[i]: 0;
803 
804  //subtract them
805  if(borrow)
806  borrow = ++right == 0; //try to add borrow to right
807 
808  m_pData[i] = left - right; //subtraction of uint32_t borrows automatically
809 
810  if(left < right)
811  borrow = true;
812  } //for
813  } //else
814 
815  normalize();
816 
817  return *this;
818 } //operator-=
819 
820 #pragma endregion subtraction
821 
823 // Division and remainder operators.
824 
825 #pragma region division
826 
831 
833  uintx_t q(0); //result
834 
835  if(y >= z){
836  uintx_t r(y), w(z);
837 
838  w <<= y.bitcount() - z.bitcount();
839 
840  while(w <= y)
841  w <<= 1;
842 
843  while(w > z){
844  q <<= 1;
845  w >>= 1;
846 
847  if(w <= r){
848  r -= w;
849  q += 1;
850  } //if
851  } //while
852  } //if
853 
854  return q;
855 } //operator/
856 
861 
862 uintx_t operator/(uintx_t y, uint32_t z){
863  return y/uintx_t(z);
864 } //operator/
865 
869 
871  return *this = *this/y;
872 } //operator/
873 
879 
881  uintx_t w(z);
882 
883  while(w <= y)
884  w <<= 1;
885 
886  while(w > z){
887  w >>= 1;
888 
889  if(w <= y)
890  y -= w;
891  } //while
892 
893  return y;
894 } //operator%
895 
899 
901  return *this = *this%y;
902 } //operator%=
903 
908 
909 uintx_t operator%(uintx_t y, uint32_t z){
910  return y%uintx_t(z);
911 } //operator%
912 
913 #pragma endregion division
bool operator>(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:371
std::string GetString() const
Get as string.
Definition: uintx_t.cpp:72
uintx_t operator/(uintx_t y, uintx_t z)
Definition: uintx_t.cpp:832
int bitcount()
Number of bits.
Definition: uintx_t.cpp:222
uintx_t & operator<<=(const int)
Left shift by.
Definition: uintx_t.cpp:528
void grow(const int s)
Grow space for s words.
Definition: uintx_t.cpp:121
uintx_t operator-(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:782
const int BitsInHalfByte
Number of bits in a nibble.
Definition: uintx_t.cpp:9
uintx_t & operator>>=(const int)
Right shift by.
Definition: uintx_t.cpp:576
uintx_t & operator *=(const uintx_t &)
Multiply by.
Definition: uintx_t.cpp:766
void reallocate(const int s)
Reallocate space for s words.
Definition: uintx_t.cpp:107
Useful includes.
uintx_t & operator/=(const uintx_t &)
Divide by.
Definition: uintx_t.cpp:870
void loadstring(const char *string)
Load hex string.
Definition: uintx_t.cpp:177
uintx_t operator+(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:290
bool operator!=(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:495
bool operator==(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:460
bool operator<(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:424
uintx_t & operator-=(const uintx_t &)
Subtract from.
Definition: uintx_t.cpp:790
Declaration of the extensible unsigned integer class.
uintx_t operator *(uintx_t y, uintx_t z)
Definition: uintx_t.cpp:686
bool operator>=(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:397
uintx_t operator%(uintx_t y, uintx_t z)
Definition: uintx_t.cpp:880
int m_nSize
Number of words in m_pData.
Definition: uintx_t.h:17
The extensible unsigned integer class.
Definition: uintx_t.h:14
~uintx_t()
Destructor.
Definition: uintx_t.cpp:58
uintx_t operator &(uintx_t x, const uintx_t &y)
Definition: uintx_t.cpp:633
uintx_t operator>>(uintx_t x, int d)
Definition: uintx_t.cpp:617
bool operator<=(uintx_t x, uintx_t y)
Definition: uintx_t.cpp:442
uintx_t & operator+=(const uintx_t &)
Add to.
Definition: uintx_t.cpp:307
const int BitsInWord
Number of bits in a word.
Definition: uintx_t.cpp:10
uint32_t * m_pData
Array of 32-bit words, least significant first.
Definition: uintx_t.h:16
void normalize()
Remove leading zero words.
Definition: uintx_t.cpp:157
uintx_t & operator%=(const uintx_t &)
Remainder.
Definition: uintx_t.cpp:900
uintx_t operator<<(uintx_t x, int d)
Definition: uintx_t.cpp:568
uintx_t & operator=(const uintx_t &)
Assignment.
Definition: uintx_t.cpp:247
const int HalfBytesInWord
Number of nibbles in a word.
Definition: uintx_t.cpp:8
uintx_t operator|(uintx_t x, const uintx_t &y)
Definition: uintx_t.cpp:656
uintx_t()
Constructor.
Definition: uintx_t.cpp:19