Xpace
integer.h
Go to the documentation of this file.
1 
2 
3 /**************************************************************
4  **
5  ** @file base/integer.h
6  **
7  ** Copyright (C) 2012 Xpace, LLC. All rights reserved
8  **
9  ** www.xpace.net
10  **
11  **************************************************************/
12 
13 #ifndef XPACE_INTEGER_H
14 #define XPACE_INTEGER_H
15 
16 #ifdef _WIN32
17 #undef min
18 #undef max
19 #endif
20 
21 #include <limits>
22 #include <vector>
23 #include <limits>
24 #include <cstring>
25 
26 #include "base/types.h"
27 
28 namespace Xpace
29 {
30  template<size_t SIZE>
31  class BigInt;
32 
33  template<size_t SIZE>
34  class BigUint
35  {
36  friend class BigInt<SIZE>;
37  public:
38  BigUint
39  (uint64 = 0);
40 
41  template<size_t RS>
42  BigUint
43  (const BigUint<RS>&);
44 
45  bool operator==
46  (const BigUint<SIZE>&)
47  const;
48  bool operator==
49  (uint)
50  const;
51  bool operator!=
52  (const BigUint<SIZE>&)
53  const;
54  bool operator<
55  (const BigUint<SIZE>& rhs)
56  const
57  {
58  return lt(rhs);
59  }
60  bool operator>
61  (const BigUint<SIZE>& rhs)
62  const
63  {
64  return gt(rhs);
65  }
66 
67  BigUint<SIZE> operator+
68  (const BigUint<SIZE>&)
69  const;
70  BigUint<SIZE> operator+
71  (uint64)
72  const;
73  BigUint<SIZE> operator-
74  (const BigUint<SIZE>&)
75  const;
76  BigUint<SIZE> operator*
77  (uint32)
78  const;
79  BigUint<SIZE> operator/
80  (uint32)
81  const;
83  (uint32,
84  uint32* rem)
85  const;
86 
87  uint64 operator[]
88  (size_t)
89  const;
90  uint64& operator[]
91  (size_t);
92  const BytesRef get
93  ()
94  const;
95  void set
96  (const BytesRef&);
97 
98  #ifdef QBYTEARRAY_H
99  operator const QByteArray
100  ()
101  const;
102  #endif
103 
104  protected:
105  bool lt
106  (const BigUint&)
107  const;
108  bool gt
109  (const BigUint&)
110  const;
111 
112  uint64 vals[SIZE];
113 
114  private:
115  static
116  uint64 add_carry
117  (uint64 a,
118  uint64 b,
119  bool* c);
120 
121  static
122  uint64 sub_borrow
123  (uint64 a,
124  uint64 b,
125  bool* borrow);
126  };
127 
128  template<size_t SIZE>
129  class BigInt : public BigUint<SIZE>
130  {
131  public:
132  BigInt
133  (int64 = 0);
134  template<size_t RS>
135  BigInt
136  (const BigInt<RS>&);
137 
138  BigInt
139  (const BigUint<SIZE>& rhs)
140  {
141  memcpy(this, &rhs, sizeof(this)); // MSVC can't see rhs.vals
142  set_minus(false);
143  }
144  operator BigUint<SIZE>
145  ()
146  const
147  {
148  BigUint<SIZE> ret;
149  memcpy(&ret.vals, &this->vals, sizeof(this->vals));
150  }
151 
152  bool operator==
153  (const BigInt&)
154  const;
155  bool operator==
156  (int)
157  const;
158  bool operator!=
159  (const BigInt&)
160  const;
161  bool operator<
162  (const BigInt&)
163  const;
164  bool operator>
165  (const BigInt&)
166  const;
167 
168  BigInt operator+
169  (const BigInt& rhs)
170  const
171  {
172  return BigUint<SIZE>(*this) + rhs;
173  }
174  BigInt operator+
175  (int64 n)
176  const
177  {
178  return BigUint<SIZE>(*this) + n;
179  }
180  BigInt operator-
181  (const BigInt& rhs)
182  const
183  {
184  return BigUint<SIZE>(*this) - rhs;
185  }
186  BigInt operator*
187  (uint32)
188  const;
189  BigInt operator/
190  (uint32)
191  const;
192  BigInt div
193  (uint32,
194  uint32* rem)
195  const;
196 
197  private:
198  bool is_minus
199  ()
200  const
201  {
202  return !!(this->vals[SIZE - 1] & 0xF000000000000000);
203  }
204 
205  uint64 strip_minus
206  (uint64 n)
207  {
208  return n & 0x7FFFFFFFFFFFFFFF;
209  }
210 
211  void set_minus
212  (bool m)
213  {
214  this->vals[SIZE - 1] = strip_minus(this->vals[SIZE - 1]) | (m ? 0xF000000000000000 : 0);
215  }
216  };
217 
218  inline
219  static int type_max
220  (int)
221  {
222  return std::numeric_limits<int>::max();
223  }
224 
225  inline
226  static uint type_max
228  {
229  return std::numeric_limits<uint>::max();
230  }
231 
232  inline
233  static int64 type_max
235  {
236  return std::numeric_limits<int64>::max();
237  }
238 
239  inline
240  static uint64 type_max
242  {
243  return std::numeric_limits<uint64>::max();
244  }
245 
246  template <size_t SIZE>
247  inline
248  static BigInt<SIZE> type_max
250  {
252  for (size_t i(0); i < SIZE - 1; ++i)
253  ret[i] = ~0;
254  ret[SIZE - 1] = std::numeric_limits<Xpace::int64>::max();
255  return ret;
256  }
257 
258  template <size_t SIZE>
259  inline
260  static BigUint<SIZE> type_max
262  {
263  BigUint<SIZE> ret;
264  for (size_t i(0); i < SIZE; ++i)
265  ret[i] = ~0;
266  return ret;
267  }
268 
269  inline
270  static int type_min
271  (int)
272  {
273  return std::numeric_limits<int>::min();
274  }
275 
276  inline
277  static uint type_min
279  {
280  return std::numeric_limits<uint>::min();
281  }
282 
283  inline
284  static int64 type_min
286  {
287  return std::numeric_limits<int64>::min();
288  }
289 
290  inline
291  static uint64 type_min
293  {
294  return std::numeric_limits<uint64>::min();
295  }
296 
297  template <size_t SIZE>
298  inline
299  static BigInt<SIZE> type_min
301  {
303  for (size_t i(0); i < SIZE - 1; ++i)
304  ret[i] = 0;
305  ret[SIZE - 1] = std::numeric_limits<Xpace::int64>::min();
306  return ret;
307  }
308 
309  template <size_t SIZE>
310  inline
311  static BigUint<SIZE> type_min
313  {
315  for (size_t i(0); i < SIZE; ++i)
316  ret[i] = 0;
317  return ret;
318  }
319 
320  template<size_t SIZE> struct Unsigned<BigInt<SIZE> > { typedef BigUint<SIZE> Type; };
321  template<size_t SIZE> struct Unsigned<BigUint<SIZE> > { typedef BigUint<SIZE> Type; };
322 
323  template<size_t SIZE> struct Signed<BigInt<SIZE> > { typedef BigInt<SIZE> Type; };
324  template<size_t SIZE> struct Signed<BigUint<SIZE> > { typedef BigInt<SIZE> Type; };
325 
326  // ================================ STRING -> INT ===========
327 
328  bool stringToUint
329  (const String8& str,
330  uint radix,
331  std::vector<uint64>* val);
332 
333  bool stringToUint
334  (const String16& str,
335  uint radix,
336  std::vector<uint64>* val);
337 
338  bool stringToInt
339  (const String8& str,
340  uint radix,
341  std::vector<uint64>* val);
342 
343  bool stringToInt
344  (const String16& str,
345  uint radix,
346  std::vector<uint64>* val);
347 
348  // ==========================================================
349  // ==========================================================
350  // ==========================================================
351 
352  // ================================ UINT ====================
353 
354  template<size_t SIZE>
355  inline
357  (uint64 v)
358  {
359  for (size_t i(SIZE); --i > 0; )
360  vals[i] = 0;
361  vals[0] = v;
362  }
363 
364  template<size_t SIZE>
365  template<size_t RS>
366  inline
368  (const BigUint<RS>& rhs)
369  {
370  if (SIZE > RS)
371  {
372  memset(vals, 0, sizeof(vals));
373  memcpy(vals, rhs.vals, sizeof(rhs.vals));
374  }
375  else
376  memcpy(vals, rhs.vals, sizeof(vals));
377  }
378 
379  template<size_t SIZE>
380  inline
382  (const BigUint<SIZE>& rhs)
383  const
384  {
385  return !memcmp(vals, rhs.vals, sizeof(vals));
386  }
387 
388  template<size_t SIZE>
389  inline
390  bool BigUint<SIZE>::operator==
391  (uint rhs)
392  const
393  {
394  if (rhs != vals[0])
395  return false;
396  for (size_t i(1); i < SIZE; ++i)
397  if (vals[i])
398  return false;
399  return true;
400  }
401 
402  template<size_t SIZE>
403  inline
404  bool BigUint<SIZE>::operator!=
405  (const BigUint<SIZE>& rhs)
406  const
407  {
408  return !(*this == rhs);
409  }
410 
411  template<size_t SIZE>
412  inline
413  bool BigUint<SIZE>::lt
414  (const BigUint<SIZE>& rhs)
415  const
416  {
417  for (size_t i(SIZE); --i; )
418  if (vals[i] > rhs.vals[i])
419  return false;
420  return vals[0] < rhs.vals[0];
421  }
422 
423  template<size_t SIZE>
424  inline
425  bool BigUint<SIZE>::gt
426  (const BigUint<SIZE>& rhs)
427  const
428  {
429  for (size_t i(SIZE); --i; )
430  if (vals[i] < rhs.vals[i])
431  return false;
432  return vals[0] > rhs.vals[0];
433  }
434 
435  template<size_t SIZE>
436  inline
437  BigUint<SIZE> BigUint<SIZE>::operator+
438  (const BigUint<SIZE>& rhs)
439  const
440  {
441  BigUint<SIZE> ret;
442  bool carry(false);
443  for (size_t i(0); i < SIZE; ++i)
444  ret.vals[i] = add_carry(vals[i], rhs.vals[i], &carry);
445  return ret;
446  }
447 
448  template<size_t SIZE>
449  inline
450  BigUint<SIZE> BigUint<SIZE>::operator+
451  (uint64 n)
452  const
453  {
454  BigUint<SIZE> ret;
455  bool carry(false);
456  ret.vals[0] = add_carry(vals[0], n, &carry);
457  for (size_t i(1); i < SIZE; ++i)
458  ret.vals[i] = add_carry(vals[i], 0, &carry);
459  return ret;
460  }
461 
462  template<size_t SIZE>
463  inline
464  BigUint<SIZE> BigUint<SIZE>::operator-
465  (const BigUint<SIZE>& rhs)
466  const
467  {
468  BigUint<SIZE> ret;
469  bool borrow(false);
470  for (size_t i(0); i < SIZE; ++i)
471  ret.vals[i] = sub_borrow(vals[i], rhs.vals[i], &borrow);
472  return ret;
473  }
474 
475  template<size_t SIZE>
476  inline
477  BigUint<SIZE> BigUint<SIZE>::operator*
478  (uint32 n)
479  const
480  {
481  BigUint<SIZE> ret;
482  uint64 rr[SIZE * 2];
483  uint64 *r(rr);
484 
485  const uint32* vv(reinterpret_cast<const uint32*>(vals));
486  for (const uint32* v(vv); v < &vv[SIZE * 2]; ++v, ++r)
487  *r = *v * n;
488 
489  bool carry(false);
490  for (uint s(0); s < SIZE; ++s)
491  ret.vals[s] = add_carry(rr[s * 2], rr[s * 2 + 1] << 32, &carry);
492 
493  return ret;
494  }
495 
496  template<size_t SIZE>
497  inline
499  (uint32 n,
500  uint32* rem)
501  const
502  {
503  BigUint<SIZE> ret;
504 
505  if (n == 1)
506  {
507  *rem = 0;
508  return *this;
509  }
510 
511  if (n == 2)
512  {
513  *rem = vals[0] & 1;
514  for (uint s(0); ; ++s)
515  {
516  ret.vals[s] = vals[s] >> 1;
517  if (s == SIZE - 1)
518  break;
519  ret.vals[s] |= (vals[s + 1] << 63);
520  }
521  }
522  else
523  {
524  // TODO: 64-bit version
525  const uint32* vals32(reinterpret_cast<const uint32*>(vals));
526  uint32* quot(reinterpret_cast<uint32*>(ret.vals));
527 
528  uint s(SIZE * 2 - 1);
529  uint64 div(vals32[s]);
530  while (1)
531  {
532  quot[s] = div / n;
533  div %= n;
534  if (s == 0)
535  {
536  *rem = div;
537  break;
538  }
539  div <<= 32;
540  div += vals32[--s];
541  }
542  }
543  return ret;
544  }
545 
546  template<size_t SIZE>
547  inline
548  BigUint<SIZE> BigUint<SIZE>::operator/
549  (uint32 n)
550  const
551  {
552  uint rem;
553  return div(n, &rem);
554  }
555 
556  template<size_t SIZE>
557  inline
558  uint64 BigUint<SIZE>::operator[]
559  (size_t i)
560  const
561  {
562  return vals[i];
563  }
564 
565  template<size_t SIZE>
566  inline
567  uint64& BigUint<SIZE>::operator[]
568  (size_t i)
569  {
570  return vals[i];
571  }
572 
573  template<size_t SIZE>
574  inline
576  ()
577  const
578  {
579  return BytesRef(reinterpret_cast<const byte*>(vals), sizeof(vals));
580  }
581 
582  template<size_t SIZE>
583  inline
584  void BigUint<SIZE>::set
585  (const BytesRef& ref)
586  {
587  if (vals.size() * sizeof(uint64) < ref.length)
588  memcpy(reinterpret_cast<byte*>(vals), ref.data, vals.size() * sizeof(uint64));
589  else
590  {
591  memcpy(reinterpret_cast<byte*>(vals), ref.data, ref.length);
592  memset(reinterpret_cast<byte*>(vals) + ref.length, 0, sizeof(vals) - ref.length);
593  }
594  }
595 
596  #ifdef QBYTEARRAY_H
597  template<size_t SIZE>
598  inline
599  BigUint<SIZE>::operator const QByteArray
600  ()
601  const
602  {
603  return QByteArray(reinterpret_cast<const char*>(vals), sizeof(vals));
604  }
605  #endif
606 
607  template<size_t SIZE>
608  inline
610  (uint64 a,
611  uint64 b,
612  bool* c)
613  {
614  *c = (*c && (a++ == ~uint64(0)))
615  ? true
616  : type_max(uint64(0)) - a < b;
617  return a + b;
618  }
619 
620  template<size_t SIZE>
621  inline
623  (uint64 a,
624  uint64 b,
625  bool* borrow)
626  {
627  *borrow = (*borrow && (a-- == 0)) ? true : a < b;
628  return a - b;
629  }
630 
631  // ================================ INT =====================
632 
633  template<size_t SIZE>
634  inline
636  (int64 n)
637  {
638  this->vals[0] = strip_minus(n);
639  set_minus(n < 0);
640  }
641 
642  template<size_t SIZE>
643  template<size_t RS>
644  inline
646  (const BigInt<RS>& rhs)
647  {
648  if (this->vals.size() > rhs.vals.size())
649  {
650  memcpy(this->vals, rhs.vals, sizeof(rhs.vals));
651  memset(&this->vals[rhs.vals.size()], 0, rhs.vals.size() - this->vals.size());
652  }
653  else
654  memcpy(this->vals, rhs.vals, sizeof(this->vals));
655  }
656 
657  template<size_t SIZE>
658  inline
660  (const BigInt<SIZE>& rhs)
661  const
662  {
663  return !memcmp(this->vals, rhs.vals, sizeof(this->vals));
664  }
665 
666  template<size_t SIZE>
667  inline
668  bool BigInt<SIZE>::operator==
669  (int rhs)
670  const
671  {
672  if ((uint64(rhs) != this->vals[0]) || (is_minus() != (rhs < 0)))
673  return false;
674  for (size_t i(1); i < SIZE; ++i)
675  if (this->vals[i])
676  return false;
677  return true;
678  }
679 
680  template<size_t SIZE>
681  inline
682  bool BigInt<SIZE>::operator!=
683  (const BigInt& rhs)
684  const
685  {
686  return !(*this == rhs);
687  }
688 
689  template<size_t SIZE>
690  inline
691  bool BigInt<SIZE>::operator<
692  (const BigInt<SIZE>& rhs)
693  const
694  {
695  return (is_minus() == rhs.is_minus()) ? lt(rhs) : is_minus();
696  }
697 
698  template<size_t SIZE>
699  inline
700  bool BigInt<SIZE>::operator>
701  (const BigInt<SIZE>& rhs)
702  const
703  {
704  return (is_minus() == rhs.is_minus()) ? gt(rhs) : rhs.is_minus();
705  }
706 
707  template<size_t SIZE>
708  inline
709  BigInt<SIZE> BigInt<SIZE>::operator*
710  (uint32 rhs)
711  const
712  {
713  BigUint<SIZE> m(*this);
714  BigInt ret(m * rhs);
715  ret.set_minus(is_minus());
716  return ret;
717  }
718 
719  template<size_t SIZE>
720  inline
721  BigInt<SIZE> BigInt<SIZE>::operator/
722  (uint32 rhs)
723  const
724  {
725  uint32 rem;
726  return div(rhs, &rem);
727  }
728 
729  template<size_t SIZE>
730  inline
732  (uint32 rhs,
733  uint32* rem)
734  const
735  {
736  BigUint<SIZE> d(*this);
737  BigInt<SIZE> ret(d.div(rhs, rem));
738  ret.set_minus(is_minus());
739  return ret;
740  }
741 }
742 
743 #endif
BigUint< SIZE > div(uint32, uint32 *rem) const
Definition: integer.h:499
const BytesRef get() const
Definition: integer.h:576
Ref< byte > BytesRef
Definition: types.h:180
unsigned int uint
Definition: types.h:75
uint64 vals[SIZE]
Definition: integer.h:112
A low-level const data holder.
Definition: types.h:165
static int type_min(int)
Definition: integer.h:271
void set(const BytesRef &)
Definition: integer.h:585
unsigned long long uint64
Definition: types.h:87
bool stringToInt(const String8 &str, uint radix, std::vector< uint64 > *val)
BigInt div(uint32, uint32 *rem) const
Definition: integer.h:732
bool stringToUint(const String8 &str, uint radix, std::vector< uint64 > *val)
bool lt(const BigUint &) const
Definition: integer.h:414
bool gt(const BigUint &) const
Definition: integer.h:426
long long int64
Definition: types.h:86
size_t length
number of Ts
Definition: types.h:170
unsigned int uint32
Definition: types.h:85
static int type_max(int)
Definition: integer.h:220
Xpace project main namespace
Definition: datetime.h:18
BigInt(int64=0)
Definition: integer.h:636
const T * data
first T
Definition: types.h:169
BigUint(uint64=0)
Definition: integer.h:357

current as of Wed Jun 10 2026 12:00:05