Algorithms_in_C++ 1.0.0
Set of algorithms implemented in C++.
Loading...
Searching...
No Matches
uint128_t.hpp
Go to the documentation of this file.
1/**
2 * @file
3 *
4 * @details Implementation of 128-bit unsigned integers.
5 * @note The implementation can be flagged as not completed. This header is used
6 * with enough operations as a part of bigger integer types 256-bit integer.
7 * @author [Ashish Daulatabad](https://github.com/AshishYUO)
8 */
9
10#include <algorithm> /// for `std::reverse` and other operations
11#include <ostream> /// for `std::cout` overload
12#include <string> /// for `std::string`
13#include <utility> /// for `std::pair` library
14
15#ifdef _MSC_VER
16#include <intrin.h> /// for _BitScanForward64 and __BitScanReverse64 operation
17#endif
18
19#ifndef CIPHERS_UINT128_T_HPP_
20#define CIPHERS_UINT128_T_HPP_
21class uint128_t;
22
23template <>
25template <>
27template <>
29
30/**
31 * @brief Adding two string
32 * @details Adds two long integer, only used for printing numbers
33 * @param first First integer string
34 * @param second Second integer string
35 * @returns string denoting the addition of both the strings
36 */
37std::string add(const std::string &first, const std::string &second) {
38 std::string third;
39 int16_t sum = 0, carry = 0;
40 for (int32_t i = static_cast<int32_t>(first.size()) - 1,
41 j = static_cast<int32_t>(second.size()) - 1;
42 i >= 0 || j >= 0; --i, --j) {
43 sum = ((i >= 0 ? first[i] - '0' : 0) + (j >= 0 ? second[j] - '0' : 0) +
44 carry);
45 carry = sum / 10;
46 sum %= 10;
47 third.push_back(sum + '0');
48 }
49 if (carry) {
50 third.push_back('1');
51 }
52 std::reverse(third.begin(), third.end());
53 return third;
54}
55/**
56 * @class uint128_t
57 * @brief class for 128-bit unsigned integer
58 */
59class uint128_t {
60 uint64_t f{}, s{}; /// First and second half of 128 bit number
61
62 /**
63 * @brief Get integer from given string.
64 * @details Create an integer from a given string
65 * @param str integer string, can be hexadecimal (starting on 0x... or
66 * number)
67 * @returns void
68 */
70 this->f = this->s = 0;
71 if (str.size() > 1 && str[1] == 'x') { // if hexadecimal
72 for (auto i = 2; i < str.size(); ++i) {
73 *this *= 16LL;
74 if (str[i] >= '0' && str[i] <= '9') {
75 *this += (str[i] - '0');
76 } else if (str[i] >= 'A' && str[i] <= 'F') {
77 *this += (str[i] - 'A' + 10);
78 } else if (str[i] >= 'a' && str[i] <= 'f') {
79 *this += (str[i] - 'a' + 10);
80 }
81 }
82 } else { // if decimal
83 for (auto &x : str) {
84 *this *= 10LL;
85 *this += (x - '0');
86 }
87 }
88 }
89
90 public:
91 uint128_t() = default;
92
93 /**
94 * @brief Parameterized constructor
95 * @tparam T integral type
96 * @param low lower part 8-bit unisgned integer
97 */
98 template <typename T, typename = typename std::enable_if<
100 explicit uint128_t(T low) : s(low) {}
101
102 /**
103 * @brief Parameterized constructor
104 * @param str Integer string (hexadecimal starting with 0x.. or decimal)
105 */
106 explicit uint128_t(const std::string &str) {
108 }
109
110 /**
111 * @brief Parameterized constructor
112 * @param high higher part 64-bit unsigned integer
113 * @param low lower part 64-bit unsigned integer
114 */
115 uint128_t(const uint64_t high, const uint64_t low) : f(high), s(low) {}
116
117 /**
118 * @brief Copy constructor
119 * @param num 128-bit unsigned integer
120 */
121 uint128_t(const uint128_t &num) = default;
122
123 /**
124 * @brief Move constructor
125 * @param num 128-bit unsigned integer
126 */
127 uint128_t(uint128_t &&num) noexcept : f(num.f), s(num.s) {}
128
129 /**
130 * @brief Destructor for uint128_t
131 */
132 ~uint128_t() = default;
133
134 /**
135 * @brief Leading zeroes in binary
136 * @details Calculates leading zeros in 128-bit integer
137 * @returns Integer denoting leading zeroes
138 */
139 inline uint32_t _lez() {
140#ifndef _MSC_VER
141 if (f) {
142 return __builtin_clzll(f);
143 }
144 return 64 + __builtin_clzll(s);
145#else
146 unsigned long r = 0;
147 _BitScanForward64(&r, f);
148 if (r == 64) {
149 unsigned long l = 0;
150 _BitScanForward64(&l, s);
151 return 64 + l;
152 }
153 return r;
154#endif
155 }
156
157 /**
158 * @brief Trailing zeroes in binary
159 * @details Calculates leading zeros in 128-bit integer
160 * @returns Integer denoting Trailing zeroes
161 */
162 inline uint32_t _trz() {
163#ifndef _MSC_VER
164 if (f) {
165 return __builtin_ctzll(f);
166 }
167 return 64 + __builtin_ctzll(s);
168#else
169 unsigned long r = 0;
170 _BitScanReverse64(&r, s);
171 if (r == 64) {
172 unsigned long l = 0;
173 _BitScanReverse64(&l, f);
174 return 64 + l;
175 }
176 return r;
177#endif
178 }
179
180 /**
181 * @brief casting operator to boolean value
182 * @returns true if value of this is non-zero, else false
183 */
184 inline explicit operator bool() const { return (f || s); }
185
186 /**
187 * @brief casting operator to any integer valu
188 * @tparam T any integer type
189 * @returns integer value casted to mentioned type
190 */
191 template <typename T, typename = typename std::enable_if<
193 inline explicit operator T() const {
194 return static_cast<T>(s);
195 }
196
197 /**
198 * @brief returns lower 64-bit integer part
199 * @returns returns lower 64-bit integer part
200 */
201 inline uint64_t lower() const { return s; }
202
203 /**
204 * @brief returns upper 64-bit integer part
205 * @returns returns upper 64-bit integer part
206 */
207 inline uint64_t upper() const { return f; }
208
209 /**
210 * @brief operator = for other types
211 * @tparam T denoting any integer type
212 * @param p an integer to assign it's value
213 * @returns this pointer with it's value equal to `p`
214 */
215 template <typename T, typename = typename std::enable_if<
217 inline uint128_t &operator=(const T &p) {
218 this->s = p;
219 return *this;
220 }
221
222 /**
223 * @brief operator = for type string
224 * @param p a string to assign it's value to equivalent integer
225 * @returns this pointer with it's value equal to `p`
226 */
227 inline uint128_t &operator=(const std::string &p) {
229 return *this;
230 }
231
232 /**
233 * @brief operator = for uint128_t
234 * @param p an 128-bit integer to assign it's value
235 * @returns this pointer with it's value equal to `p`
236 */
237 inline uint128_t &operator=(const uint128_t &p) = default;
238
239 /**
240 * @brief Move assignment operator
241 */
242 inline uint128_t &operator=(uint128_t &&p) = default;
243
244 /**
245 * @brief operator + for uint128_t and other integer types.
246 * @tparam T denoting integral type
247 * @param p a type of integer variable
248 * @returns addition of this and p, returning uint128_t integer
249 */
250 template <typename T, typename = typename std::enable_if<
252 inline uint128_t operator+(const T p) {
253 return uint128_t(f + (p + s < s), p + s);
254 }
255
256 /**
257 * @brief operator + for uint128_t and other integer types.
258 * @param p 128-bit unsigned integer
259 * @returns addition of this and p, returning uint128_t integer
260 */
261 inline uint128_t operator+(const uint128_t &p) {
262 return uint128_t(f + (p.s + s < s) + p.f, p.s + s);
263 }
264
265 /**
266 * @brief operator += for uint128_t and other integer types.
267 * @tparam T denoting integral type
268 * @param p a type of integer variable
269 * @returns addition of this and p, returning this
270 */
271 template <typename T, typename = typename std::enable_if<
273 inline uint128_t &operator+=(const T p) {
274 bool app = p + s < s;
275 this->f += app;
276 this->s += p;
277 return *this;
278 }
279
280 /**
281 * @brief operator += for uint128_t
282 * @param p 128-bit unsigned integer
283 * @returns addition of this and p, returning this
284 */
286 bool app = p.s + s < s;
287 f = f + app + p.f;
288 s = p.s + s;
289 return *this;
290 }
291
292 /**
293 * @brief pre-increment operator
294 * @returns incremented value of this.
295 */
297 *this += 1;
298 return *this;
299 }
300
301 /**
302 * @brief post-increment operator
303 * @returns incremented value of this.
304 */
305 inline uint128_t operator++(int) {
306 ++*this;
307 return *this;
308 }
309
310 /**
311 * @brief operator - for uint128_t and other integer types.
312 * @tparam T denoting integral type
313 * @param p a type of integer variable
314 * @returns subtraction of this and p, returning uint128_t integer
315 */
316 template <typename T, typename = typename std::enable_if<
318 inline uint128_t operator-(const T &p) {
319 bool app = p > s;
320 return uint128_t(f - app, s - p);
321 }
322
323 /**
324 * @brief operator - for uint128_t
325 * @param p a type of integer variable
326 * @returns subtraction of this and p, returning uint128_t integer
327 */
328 inline uint128_t operator-(const uint128_t &p) {
329 bool app = p.s > s;
330 return uint128_t(f - p.f - app, s - p.s);
331 }
332
333 /**
334 * @brief operator - using twos complement
335 * @returns 2's complement of this.
336 */
337 inline uint128_t operator-() { return ~*this + uint128_t(1); }
338
339 /**
340 * @brief operator -- (pre-decrement)
341 * @returns decremented value of this
342 */
344 *this -= 1;
345 return *this;
346 }
347
348 /**
349 * @brief operator -- (post-decrement)
350 * @returns decremented value of this
351 */
352 inline uint128_t operator--(int p) {
353 --*this;
354 return *this;
355 }
356
357 /**
358 * @brief operator -= for uint128_t and other integer types.
359 * @tparam T denoting integral type
360 * @param p a type of integer variable
361 * @returns subtraction of this and p, returning this
362 */
363 template <typename T, typename = typename std::enable_if<
365 uint128_t &operator-=(const T &p) {
366 bool app = p > s;
367 f -= app;
368 s -= p;
369 return *this;
370 }
371
372 /**
373 * @brief operator -= for uint128_t
374 * @param p 128-bit unsigned integer
375 * @returns subtraction of this and p, returning this
376 */
378 bool app = p.s > s;
379 f = f - p.f - app;
380 s = s - p.s;
381 return *this;
382 }
383
384 /**
385 * @brief operator * for uint128_t and other integer types.
386 * @tparam T denoting integral type
387 * @param p a type of integer variable
388 * @returns multiplication of this and p, returning uint128_t integer
389 */
390 template <typename T, typename = typename std::enable_if<
392 inline uint128_t operator*(const T p) {
393 return *this * uint128_t(p);
394 }
395
396 /**
397 * @brief operator * for uint128_t and other integer types.
398 * @param p 128-bit unsigned integer
399 * @returns multiplication of this and p, returning uint128_t integer
400 */
402 uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF,
403 s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF;
404 uint64_t fi = f_first * s_first, se = f_first * s_second,
405 th = s_first * f_second, fo = s_second * f_second;
406 uint64_t tmp = ((se & 0xFFFFFFFF) << 32), tmp2 = (th & 0xFFFFFFFF)
407 << 32;
408 int cc = (tmp + tmp2 < tmp);
409 tmp += tmp2;
410 cc += (tmp + fo < tmp);
411 uint64_t carry = fi + (se >> 32) + (th >> 32);
412 return uint128_t(this->f * p.s + this->s * p.f + carry + cc, tmp + fo);
413 }
414
415 /**
416 * @brief operator *= for uint128_t and other integer types.
417 * @tparam T denoting integral type
418 * @param p a type of integer variable
419 * @returns multiplication of this and p, returning this
420 */
421 template <typename T, typename = typename std::enable_if<
423 inline uint128_t &operator*=(const T p) {
424 *this *= uint128_t(p);
425 return *this;
426 }
427
428 /**
429 * @brief operator *= for uint128_t and other integer types.
430 * @param p 128-bit unsigned integer
431 * @returns multiplication of this and p, returning this
432 */
434 uint64_t f_first = s >> 32, f_second = s & 0xFFFFFFFF,
435 s_first = p.s >> 32, s_second = p.s & 0xFFFFFFFF;
436 uint64_t fi = f_first * s_first, se = f_first * s_second,
437 th = s_first * f_second, fo = s_second * f_second;
438 uint64_t tmp = (se << 32), tmp2 = (th << 32);
439 int cc = (tmp + tmp2 < tmp);
440 tmp += tmp2;
441 cc += (tmp + fo < tmp);
442 uint64_t carry = fi + (se >> 32) + (th >> 32);
443 f = this->f * p.s + this->s * p.f + carry + cc;
444 s = tmp + fo;
445 return *this;
446 }
447
448 /**
449 * @brief divide function for uint128_t and other integer types.
450 * @details divide this value and
451 * @param p 128-bit unsigned integer
452 * @returns pair denoting quotient and remainder.
453 */
455 if (*this < p) { // if this is less than divisor
456 return {uint128_t(0), *this};
457 } else if (*this == p) { // if this is equal to divisor
458 return {uint128_t(1), uint128_t(0)};
459 }
460 uint128_t tmp = p, tmp2 = *this;
461 uint16_t left = tmp._lez() - _lez();
462 tmp <<= left;
463 uint128_t quotient(0);
464 uint128_t zero(0);
465 while (tmp2 >= p) {
466 uint16_t shf = tmp2._lez() - tmp._lez();
467 if (shf) {
468 tmp >>= shf;
469 quotient <<= shf;
470 left -= shf;
471 }
472 if (tmp2 < tmp) {
473 tmp >>= 1;
474 quotient <<= 1;
475 --left;
476 }
477 tmp2 -= tmp;
478 ++quotient;
479 }
480 return {quotient << left, tmp2};
481 }
482
483 /**
484 * @brief operator / for uint128_t and other integer types.
485 * @param p 128-bit unsigned integer
486 * @returns unsigned 128-bit quotient.
487 */
488 inline uint128_t operator/(const uint128_t &p) { return divide(p).first; }
489
490 /**
491 * @brief operator / for uint128_t and other integer types.
492 * @tparam T denoting integral type
493 * @param p a type of integer variable
494 * @returns unsigned 128-bit quotient.
495 */
496 template <typename T, typename = typename std::enable_if<
498 inline uint128_t operator/(const T p) {
499 uint128_t tmp = *this;
500 tmp /= uint128_t(0, p);
501 return tmp;
502 }
503
504 /**
505 * @brief operator /= for uint128_t
506 * @param p 128-bit unsigned integer
507 * @returns this set as unsigned 128-bit quotient.
508 */
509 inline uint128_t &operator/=(const uint128_t &p) {
510 *this = divide(p).first;
511 return *this;
512 }
513
514 /**
515 * @brief operator /= for uint128_t and other integer types.
516 * @tparam T denoting integral type
517 * @param p a type of integer variable
518 * @returns this set as unsigned 128-bit quotient.
519 */
520 template <typename T, typename = typename std::enable_if<
522 inline uint128_t &operator/=(const T p) {
523 *this /= uint128_t(0, p);
524 return *this;
525 }
526
527 /**
528 * @brief operator % for uint128_t
529 * @param p 128-bit unsigned integer
530 * @returns unsigned 128-bit remainder.
531 */
532 inline uint128_t operator%(const uint128_t &p) { return divide(p).second; }
533
534 /**
535 * @brief operator % for uint128_t and other integer types.
536 * @tparam T denoting integral type
537 * @param p a type of integer variable
538 * @returns unsigned 128-bit remainder.
539 */
540 template <typename T, typename = typename std::enable_if<
542 inline uint128_t operator%(const T &p) {
543 return *this % uint128_t(p);
544 }
545
546 /**
547 * @brief operator %= for uint128_t
548 * @param p 128-bit unsigned integer
549 * @returns this set as unsigned 128-bit remainder.
550 */
551 inline uint128_t &operator%=(const uint128_t &p) {
552 *this = divide(p).second;
553 return *this;
554 }
555
556 /**
557 * @brief operator %= for uint128_t
558 * @tparam T denoting integral type
559 * @param p a type of integer variable
560 * @returns this set as unsigned 128-bit remainder.
561 */
562 template <typename T, typename = typename std::enable_if<
564 inline uint128_t &operator%=(const T &p) {
565 *this %= uint128_t(p);
566 return *this;
567 }
568
569 /**
570 * @brief operator < for uint128_t
571 * @param other number to be compared with this
572 * @returns true if this is less than other, else false
573 */
574 inline bool operator<(const uint128_t &other) {
575 return f < other.f || (f == other.f && s < other.s);
576 }
577
578 /**
579 * @brief operator <= for uint128_t
580 * @param other number to be compared with this
581 * @returns true if this is less than or equal to other, else false
582 */
583 inline bool operator<=(const uint128_t &other) {
584 return f < other.f || (f == other.f && s <= other.s);
585 }
586
587 /**
588 * @brief operator > for uint128_t
589 * @param other number to be compared with this
590 * @returns true if this is greater than other, else false
591 */
592 inline bool operator>(const uint128_t &other) {
593 return f > other.f || (f == other.f && s > other.s);
594 }
595
596 /**
597 * @brief operator >= for uint128_t
598 * @param other number to be compared with this
599 * @returns true if this is greater than or equal than other, else false
600 */
601 inline bool operator>=(const uint128_t &other) {
602 return (f > other.f) || (f == other.f && s >= other.s);
603 }
604
605 /**
606 * @brief operator == for uint128_t
607 * @param other number to be compared with this
608 * @returns true if this is equal than other, else false
609 */
610 inline bool operator==(const uint128_t &other) {
611 return f == other.f && s == other.s;
612 }
613
614 /**
615 * @brief operator != for uint128_t
616 * @param other number to be compared with this
617 * @returns true if this is not equal than other, else false
618 */
619 inline bool operator!=(const uint128_t &other) {
620 return f != other.f || s != other.s;
621 }
622
623 /**
624 * @brief operator ! for uint128_t
625 * @returns true if this has zero value, else false
626 */
627 inline bool operator!() { return !f && !s; }
628
629 /**
630 * @brief operator && for uint128_t
631 * @param b number to be compared with this
632 * @returns true if both of the values are not zero, else false
633 */
634 inline bool operator&&(const uint128_t &b) {
635 return (s || f) && (b.s || b.f);
636 }
637
638 /**
639 * @brief operator || for uint128_t
640 * @param b number to be compared with this
641 * @returns true if one of the values are not zero, else false
642 */
643 inline bool operator||(const uint128_t &b) {
644 return (s || f) || (b.s || b.f);
645 }
646
647 /**
648 * @brief operator () for uint128_t
649 * @returns true if this value is non-zero, else false
650 */
651 inline bool operator()() { return s || f; }
652
653 /**
654 * @brief operator < for other types
655 * @tparam T integral type
656 * @param other number to be compared with this
657 * @returns true if this is less than other, else false
658 */
659 template <typename T, typename = typename std::enable_if<
661 inline bool operator<(const T other) {
662 return *this < uint128_t(other);
663 }
664
665 /**
666 * @brief operator <= for other types
667 * @tparam T integral type
668 * @param other number to be compared with this
669 * @returns true if this is less than or equal to other, else false
670 */
671 template <typename T, typename = typename std::enable_if<
673 inline bool operator<=(const T other) {
674 return *this <= uint128_t(other);
675 }
676
677 /**
678 * @brief operator > for other types
679 * @tparam T integral type
680 * @param other number to be compared with this
681 * @returns true if this is greater than other, else false
682 */
683 template <typename T, typename = typename std::enable_if<
685 inline bool operator>(const T other) {
686 return *this > uint128_t(other);
687 }
688
689 /**
690 * @brief operator >= for other types
691 * @tparam T integral type
692 * @param other number to be compared with this
693 * @returns true if this is greater than or equal other, else false
694 */
695 template <typename T, typename = typename std::enable_if<
697 inline bool operator>=(const T other) {
698 return *this >= uint128_t(other);
699 }
700
701 /**
702 * @brief operator == for other types
703 * @tparam T integral type
704 * @param other number to be compared with this
705 * @returns true if this is equal to other, else false
706 */
707 template <typename T, typename = typename std::enable_if<
709 inline bool operator==(const T other) {
710 return *this == uint128_t(other);
711 }
712
713 /**
714 * @brief operator != for other types
715 * @tparam T integral type
716 * @param other number to be compared with this
717 * @returns true if this is not equal to other, else false
718 */
719 template <typename T, typename = typename std::enable_if<
721 inline bool operator!=(const T other) {
722 return *this != uint128_t(other);
723 }
724
725 /**
726 * @brief operator && for other types
727 * @tparam T integral type
728 * @param other number to be compared with this
729 * @returns true if this is both values are non-zero, else false
730 */
731 template <typename T, typename = typename std::enable_if<
733 inline bool operator&&(const T b) {
734 return (f || s) && b;
735 }
736
737 /**
738 * @brief operator || for other types
739 * @tparam T integral type
740 * @param other number to be compared with this
741 * @returns true if this is either one of the values are non-zero, else
742 * false
743 */
744 template <typename T, typename = typename std::enable_if<
746 inline bool operator||(const T b) {
747 return (f || s) || b;
748 }
749
750 /**
751 * @brief operator ~ for uint128_t
752 * @returns 1's complement of this number
753 */
754 uint128_t operator~() { return uint128_t(~this->f, ~this->s); }
755
756 /**
757 * @brief operator << for uint128_t
758 * @tparam T integral type
759 * @param p number denoting number of shifts
760 * @returns value of this shifted by p to left
761 */
762 template <typename T, typename = typename std::enable_if<
765 if (!p) {
766 return uint128_t(f, s);
767 } else if (p >= 64 && p <= 128) {
768 return uint128_t((this->s << (p - 64)), 0);
769 } else if (p < 64 && p > 0) {
770 return uint128_t((this->f << p) + ((this->s >> (64 - p))),
771 this->s << p);
772 }
773 return uint128_t(0);
774 }
775
776 /**
777 * @brief operator <<= for uint128_t
778 * @tparam T integral type
779 * @param p number denoting number of shifts
780 * @returns this shifted by p to left
781 */
782 template <typename T, typename = typename std::enable_if<
784 uint128_t &operator<<=(const T p) {
785 if (p) {
786 if (p >= 64 && p <= 128) {
787 this->f = (this->s << (p - 64));
788 this->s = 0;
789 } else {
790 f = ((this->f << p) + (this->s >> (64 - p)));
791 s = (this->s << p);
792 }
793 }
794 return *this;
795 }
796
797 /**
798 * @brief operator >> for uint128_t
799 * @tparam T integral type
800 * @param p number denoting number of shifts
801 * @returns value of this shifted by p to right
802 */
803 template <typename T, typename = typename std::enable_if<
806 if (!p) {
807 return uint128_t(this->f, this->s);
808 } else if (p >= 64 && p <= 128) {
809 return uint128_t(0, (this->f >> (p - 64)));
810 } else if (p < 64 && p > 0) {
811 return uint128_t((this->f >> p),
812 (this->s >> p) + (this->f << (64 - p)));
813 }
814 return uint128_t(0);
815 }
816
817 /**
818 * @brief operator >>= for uint128_t
819 * @tparam T integral type
820 * @param p number denoting number of shifts
821 * @returns this shifted by p to right
822 */
823 template <typename T, typename = typename std::enable_if<
825 uint128_t &operator>>=(const T p) {
826 if (p) {
827 if (p >= 64) {
828 f = 0;
829 s = (this->f >> (p - 64));
830 } else {
831 s = (this->s >> p) + (this->f << (64 - p));
832 f = (this->f >> p);
833 }
834 }
835 return *this;
836 }
837
838 /**
839 * @brief operator & for uint128_t (bitwise operator)
840 * @param p number to be operated
841 * @returns value of this & p (& is bit-wise operator)
842 */
843 inline uint128_t operator&(const uint128_t &p) {
844 return uint128_t(this->f & p.f, this->s & p.s);
845 }
846
847 /**
848 * @brief operator & for other types (bitwise operator)
849 * @tparam T integral type
850 * @param p number to be operated
851 * @returns value of this & p (& is bit-wise operator)
852 */
853 template <typename T, typename = typename std::enable_if<
855 uint128_t operator&(const T p) {
856 uint128_t tmp = *this;
857 return tmp & uint128_t(p);
858 }
859
860 /**
861 * @brief operator &= for uint128_t (bitwise operator)
862 * @param p number to be operated
863 * @returns this = this & p (& is bit-wise operator)
864 */
866 this->f &= p.f;
867 this->s &= p.s;
868 return *this;
869 }
870
871 /**
872 * @brief operator &= for other types (bitwise operator)
873 * @tparam T integral type
874 * @param p number to be operated
875 * @returns this = this & p (& is bit-wise operator)
876 */
877 template <typename T, typename = typename std::enable_if<
879 uint128_t &operator&=(const T p) {
880 *this &= uint128_t(p);
881 return *this;
882 }
883
884 /**
885 * @brief operator | for other types (bitwise operator)
886 * @tparam T integral type
887 * @param p number to be operated
888 * @returns value of this | p (| is bit-wise operator)
889 */
890 template <typename T, typename = typename std::enable_if<
892 inline uint128_t operator|(const T p) {
893 return uint128_t(p | s);
894 }
895
896 /**
897 * @brief operator | for uint128_t (bitwise operator)
898 * @param p number to be operated
899 * @returns value of this | p (| is bit-wise OR operator)
900 */
901 inline uint128_t operator|(const uint128_t &p) {
902 return uint128_t(this->f | p.f, this->s | p.s);
903 }
904
905 /**
906 * @brief operator |= for uint128_t (bitwise operator)
907 * @param p number to be operated
908 * @returns this = this | p (| is bit-wise OR operator)
909 */
911 f |= p.f;
912 s |= p.s;
913 return *this;
914 }
915
916 /**
917 * @brief operator |= for other types (bitwise operator)
918 * @tparam T integral type
919 * @param p number to be operated
920 * @returns this = this | p (| is bit-wise OR operator)
921 */
922 template <typename T, typename = typename std::enable_if<
924 inline uint128_t &operator|=(const T p) {
925 s |= p.s;
926 return *this;
927 }
928
929 /**
930 * @brief operator ^ for other types (bitwise operator)
931 * @tparam T integral type
932 * @param p number to be operated
933 * @returns value of this ^ p (^ is bit-wise XOR operator)
934 */
935 template <typename T, typename = typename std::enable_if<
937 inline uint128_t operator^(const T p) {
938 return uint128_t(this->f, this->s ^ p);
939 }
940
941 /**
942 * @brief operator ^ for uint128_t (bitwise operator)
943 * @param p number to be operated
944 * @returns value of this ^ p (^ is bit-wise XOR operator)
945 */
946 inline uint128_t operator^(const uint128_t &p) {
947 return uint128_t(this->f ^ p.f, this->s ^ p.s);
948 }
949
950 /**
951 * @brief operator ^= for uint128_t (bitwise operator)
952 * @param p number to be operated
953 * @returns this = this ^ p (^ is bit-wise XOR operator)
954 */
956 f ^= p.f;
957 s ^= p.s;
958 return *this;
959 }
960
961 /**
962 * @brief operator ^= for other types (bitwise operator)
963 * @tparam T integral type
964 * @param p number to be operated
965 * @returns this = this ^ p (^ is bit-wise XOR operator)
966 */
967 template <typename T, typename = typename std::enable_if<
969 inline uint128_t &operator^=(const T &p) {
970 s ^= p;
971 return *this;
972 }
973
974 /**
975 * @brief operator << for printing uint128_t integer
976 * @details Prints the uint128_t integer in decimal form
977 * @note Note that this operator is costly since it uses strings to print
978 * the value
979 * @param op ostream object
980 * @param p 128-bit integer
981 * @returns op, ostream object.
982 */
984 if (!p.f) {
985 op << p.s;
986 } else {
987 std::string out = "0", p_2 = "1";
988 for (int i = 0; i < 64; ++i) {
989 if (p.s & (1LL << i)) {
990 out = add(out, p_2);
991 }
992 p_2 = add(p_2, p_2);
993 }
994 for (int i = 0; i < 64; ++i) {
995 if (p.f & (1LL << i)) {
996 out = add(out, p_2);
997 }
998 p_2 = add(p_2, p_2);
999 }
1000 op << out;
1001 }
1002 return op;
1003 }
1004};
1005
1006// Arithmetic operators
1007template <typename T, typename = typename std::enable_if<
1009inline uint128_t operator+(const T &p, const uint128_t &q) {
1010 return uint128_t(p) + q;
1011}
1012
1013template <typename T, typename = typename std::enable_if<
1015inline uint128_t operator-(const T p, const uint128_t &q) {
1016 return uint128_t(p) - q;
1017}
1018
1019template <typename T, typename = typename std::enable_if<
1021inline uint128_t operator*(const T p, const uint128_t &q) {
1022 return uint128_t(p) * q;
1023}
1024
1025template <typename T, typename = typename std::enable_if<
1027inline uint128_t operator/(const T p, const uint128_t &q) {
1028 return uint128_t(p) / q;
1029}
1030
1031template <typename T, typename = typename std::enable_if<
1033inline uint128_t operator%(const T p, const uint128_t &q) {
1034 return uint128_t(p) % q;
1035}
1036
1037// Bitwise operators
1038template <typename T, typename = typename std::enable_if<
1040inline uint128_t operator&(const T &p, const uint128_t &q) {
1041 return uint128_t(p) & q;
1042}
1043
1044template <typename T, typename = typename std::enable_if<
1046inline uint128_t operator|(const T p, const uint128_t &q) {
1047 return uint128_t(p) | q;
1048}
1049
1050template <typename T, typename = typename std::enable_if<
1052inline uint128_t operator^(const T p, const uint128_t &q) {
1053 return uint128_t(p) ^ q;
1054}
1055
1056// Boolean operators
1057template <typename T, typename = typename std::enable_if<
1059inline bool operator&&(const T p, const uint128_t &q) {
1060 return uint128_t(p) && q;
1061}
1062
1063template <typename T, typename = typename std::enable_if<
1065inline bool operator||(const T p, const uint128_t &q) {
1066 return uint128_t(p) || q;
1067}
1068
1069// Comparison operators
1070template <typename T, typename = typename std::enable_if<
1072inline bool operator==(const T p, const uint128_t &q) {
1073 return uint128_t(p) == q;
1074}
1075
1076template <typename T, typename = typename std::enable_if<
1078inline bool operator!=(const T p, const uint128_t &q) {
1079 return uint128_t(p) != q;
1080}
1081
1082template <typename T, typename = typename std::enable_if<
1084inline bool operator<(const T p, const uint128_t &q) {
1085 return uint128_t(p) < q;
1086}
1087
1088template <typename T, typename = typename std::enable_if<
1090inline bool operator<=(const T p, const uint128_t &q) {
1091 return uint128_t(p) <= q;
1092}
1093
1094template <typename T, typename = typename std::enable_if<
1096inline bool operator>(const T p, const uint128_t &q) {
1097 return uint128_t(p) > q;
1098}
1099
1100template <typename T, typename = typename std::enable_if<
1102inline bool operator>=(const T p, const uint128_t &q) {
1103 return uint128_t(p) >= q;
1104}
1105
1106#endif // CIPHERS_UINT128_T_HPP_
T begin(T... args)
class for 128-bit unsigned integer
Definition uint128_t.hpp:59
uint128_t & operator%=(const T &p)
operator %= for uint128_t
Definition uint128_t.hpp:564
uint128_t operator-()
operator - using twos complement
Definition uint128_t.hpp:337
uint128_t & operator-=(const T &p)
operator -= for uint128_t and other integer types.
Definition uint128_t.hpp:365
bool operator&&(const T b)
operator && for other types
Definition uint128_t.hpp:733
uint128_t & operator>>=(const T p)
operator >>= for uint128_t
Definition uint128_t.hpp:825
uint128_t(const std::string &str)
Parameterized constructor.
Definition uint128_t.hpp:106
uint128_t operator+(const uint128_t &p)
operator + for uint128_t and other integer types.
Definition uint128_t.hpp:261
uint128_t operator<<(const T p)
operator << for uint128_t
Definition uint128_t.hpp:764
bool operator<=(const uint128_t &other)
operator <= for uint128_t
Definition uint128_t.hpp:583
uint128_t & operator--()
operator – (pre-decrement)
Definition uint128_t.hpp:343
uint64_t upper() const
returns upper 64-bit integer part
Definition uint128_t.hpp:207
uint128_t & operator&=(const T p)
operator &= for other types (bitwise operator)
Definition uint128_t.hpp:879
uint128_t & operator%=(const uint128_t &p)
operator %= for uint128_t
Definition uint128_t.hpp:551
bool operator>(const uint128_t &other)
operator > for uint128_t
Definition uint128_t.hpp:592
uint128_t operator--(int p)
operator – (post-decrement)
Definition uint128_t.hpp:352
uint128_t operator|(const uint128_t &p)
operator | for uint128_t (bitwise operator)
Definition uint128_t.hpp:901
uint128_t & operator/=(const uint128_t &p)
operator /= for uint128_t
Definition uint128_t.hpp:509
uint128_t & operator*=(const T p)
operator *= for uint128_t and other integer types.
Definition uint128_t.hpp:423
uint128_t operator/(const uint128_t &p)
operator / for uint128_t and other integer types.
Definition uint128_t.hpp:488
bool operator||(const uint128_t &b)
operator || for uint128_t
Definition uint128_t.hpp:643
bool operator>=(const T other)
operator >= for other types
Definition uint128_t.hpp:697
uint128_t & operator=(uint128_t &&p)=default
Move assignment operator.
uint128_t operator|(const T p)
operator | for other types (bitwise operator)
Definition uint128_t.hpp:892
~uint128_t()=default
Destructor for uint128_t.
uint128_t operator~()
operator ~ for uint128_t
Definition uint128_t.hpp:754
uint128_t operator*(const uint128_t &p)
operator * for uint128_t and other integer types.
Definition uint128_t.hpp:401
uint128_t & operator^=(const T &p)
operator ^= for other types (bitwise operator)
Definition uint128_t.hpp:969
bool operator<=(const T other)
operator <= for other types
Definition uint128_t.hpp:673
uint128_t operator*(const T p)
operator * for uint128_t and other integer types.
Definition uint128_t.hpp:392
uint128_t operator+(const T p)
operator + for uint128_t and other integer types.
Definition uint128_t.hpp:252
uint128_t & operator+=(const T p)
operator += for uint128_t and other integer types.
Definition uint128_t.hpp:273
bool operator<(const T other)
operator < for other types
Definition uint128_t.hpp:661
friend std::ostream & operator<<(std::ostream &op, const uint128_t &p)
operator << for printing uint128_t integer
Definition uint128_t.hpp:983
uint128_t(const uint128_t &num)=default
Copy constructor.
uint128_t & operator|=(const T p)
operator |= for other types (bitwise operator)
Definition uint128_t.hpp:924
uint128_t operator-(const T &p)
operator - for uint128_t and other integer types.
Definition uint128_t.hpp:318
uint128_t operator>>(const T p)
operator >> for uint128_t
Definition uint128_t.hpp:805
bool operator!=(const T other)
operator != for other types
Definition uint128_t.hpp:721
bool operator==(const T other)
operator == for other types
Definition uint128_t.hpp:709
bool operator==(const uint128_t &other)
operator == for uint128_t
Definition uint128_t.hpp:610
uint32_t _trz()
Trailing zeroes in binary.
Definition uint128_t.hpp:162
uint128_t(uint128_t &&num) noexcept
Move constructor.
Definition uint128_t.hpp:127
bool operator||(const T b)
operator || for other types
Definition uint128_t.hpp:746
uint128_t operator-(const uint128_t &p)
operator - for uint128_t
Definition uint128_t.hpp:328
bool operator>(const T other)
operator > for other types
Definition uint128_t.hpp:685
void __get_integer_from_string(const std::string &str)
First and second half of 128 bit number.
Definition uint128_t.hpp:69
std::pair< uint128_t, uint128_t > divide(const uint128_t &p)
divide function for uint128_t and other integer types.
Definition uint128_t.hpp:454
uint128_t operator^(const uint128_t &p)
operator ^ for uint128_t (bitwise operator)
Definition uint128_t.hpp:946
uint128_t(const uint64_t high, const uint64_t low)
Parameterized constructor.
Definition uint128_t.hpp:115
uint128_t & operator*=(const uint128_t &p)
operator *= for uint128_t and other integer types.
Definition uint128_t.hpp:433
uint128_t & operator+=(const uint128_t &p)
operator += for uint128_t
Definition uint128_t.hpp:285
uint128_t operator&(const T p)
operator & for other types (bitwise operator)
Definition uint128_t.hpp:855
uint128_t & operator<<=(const T p)
operator <<= for uint128_t
Definition uint128_t.hpp:784
uint64_t lower() const
returns lower 64-bit integer part
Definition uint128_t.hpp:201
uint128_t & operator/=(const T p)
operator /= for uint128_t and other integer types.
Definition uint128_t.hpp:522
uint128_t operator^(const T p)
operator ^ for other types (bitwise operator)
Definition uint128_t.hpp:937
bool operator&&(const uint128_t &b)
operator && for uint128_t
Definition uint128_t.hpp:634
bool operator!=(const uint128_t &other)
operator != for uint128_t
Definition uint128_t.hpp:619
uint128_t & operator=(const uint128_t &p)=default
operator = for uint128_t
uint128_t & operator|=(const uint128_t &p)
operator |= for uint128_t (bitwise operator)
Definition uint128_t.hpp:910
uint128_t & operator=(const std::string &p)
operator = for type string
Definition uint128_t.hpp:227
uint128_t & operator-=(const uint128_t &p)
operator -= for uint128_t
Definition uint128_t.hpp:377
uint128_t operator%(const uint128_t &p)
operator % for uint128_t
Definition uint128_t.hpp:532
uint128_t & operator&=(const uint128_t &p)
operator &= for uint128_t (bitwise operator)
Definition uint128_t.hpp:865
uint128_t & operator++()
pre-increment operator
Definition uint128_t.hpp:296
uint128_t & operator=(const T &p)
operator = for other types
Definition uint128_t.hpp:217
bool operator<(const uint128_t &other)
operator < for uint128_t
Definition uint128_t.hpp:574
uint128_t operator&(const uint128_t &p)
operator & for uint128_t (bitwise operator)
Definition uint128_t.hpp:843
bool operator!()
operator ! for uint128_t
Definition uint128_t.hpp:627
uint128_t(T low)
Parameterized constructor.
Definition uint128_t.hpp:100
uint128_t operator%(const T &p)
operator % for uint128_t and other integer types.
Definition uint128_t.hpp:542
uint128_t & operator^=(const uint128_t &p)
operator ^= for uint128_t (bitwise operator)
Definition uint128_t.hpp:955
bool operator>=(const uint128_t &other)
operator >= for uint128_t
Definition uint128_t.hpp:601
uint128_t operator/(const T p)
operator / for uint128_t and other integer types.
Definition uint128_t.hpp:498
uint32_t _lez()
Leading zeroes in binary.
Definition uint128_t.hpp:139
bool operator()()
operator () for uint128_t
Definition uint128_t.hpp:651
uint128_t operator++(int)
post-increment operator
Definition uint128_t.hpp:305
T end(T... args)
T operator!=(T... args)
T push_back(T... args)
T reverse(T... args)
T size(T... args)
std::string add(const std::string &first, const std::string &second)
Adding two string.
Definition uint128_t.hpp:37