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