Aesi Multiprecision
C++ class library of long integer arithmetic for GPU parallelization
Loading...
Searching...
No Matches
Aeu.h
Go to the documentation of this file.
1
31#ifndef AEU_MULTIPRECISION
32#define AEU_MULTIPRECISION
33
35#include <iostream>
36#include <cassert>
37
38#ifdef __CUDACC__
39#define gpu __host__ __device__
40 #include <cuda/std/utility>
41 #include <cuda/std/array>
42#else
43#define gpu
44 #include <utility>
45 #include <array>
46#endif
48
49#if defined AESI_UNSAFE
50 #warning Enabled nightly mode for the library. Functions and methods input arguments are not checked for validity. Be really gentle
51#endif
52
53#ifdef AESI_CRYPTOPP_INTEGRATION
54#include <cryptopp/integer.h>
55#endif
56
57#ifdef AESI_GMP_INTEGRATION
58#include <gmpxx.h>
59#endif
60
61namespace {
62 using byte = uint8_t;
63 using block = uint32_t;
64
65 constexpr inline std::size_t bitsInByte = 8;
66 constexpr inline std::size_t blockBitLength = sizeof(block) * bitsInByte;
67 constexpr inline uint64_t blockBase = 1ULL << blockBitLength;
68 constexpr inline block blockMax = 0xff'ff'ff'ffu;
69
74 enum class Comparison { equal = 0, less = 1, greater = 2, equivalent = 3 };
75}
76
82template <std::size_t bitness = 512> requires (bitness % blockBitLength == 0)
83class Aeu final {
84 static_assert(bitness > sizeof(uint64_t), "Use built-in types for numbers 64-bit or less.");
85
86 static constexpr std::size_t blocksNumber = bitness / blockBitLength;
87
88#ifdef __CUDACC__
89 template <typename T1, typename T2>
90 using pair = cuda::std::pair<T1, T2>;
91 using blockLine = cuda::std::array<block, blocksNumber>;
92#else
93 template<typename T1, typename T2>
94 using pair = std::pair<T1, T2>;
95 using blockLine = std::array<block, blocksNumber>;
96#endif
97
98 /* -------------------------- @name Class members. ----------------------- */
102 blockLine blocks;
103 /* ----------------------------------------------------------------------- */
104
105 /* ------------------------ @name Helper functions. ---------------------- */
112 gpu static constexpr auto addLine(blockLine& dst, const blockLine& src) noexcept -> uint64_t {
113 uint64_t carryOut = 0;
114 for (std::size_t i = 0; i < blocksNumber; ++i) {
115 uint64_t sum = static_cast<uint64_t>(dst[i]) + static_cast<uint64_t>(src[i]) + carryOut;
116 carryOut = sum / blockBase; dst[i] = static_cast<block>(sum % blockBase);
117 }
118 return carryOut;
119 }
120
126 gpu static constexpr auto makeComplement(blockLine& line) noexcept -> uint64_t {
127 uint64_t carryOut = 1;
128 for(std::size_t i = 0; i < blocksNumber; ++i) {
129 const uint64_t sum = blockBase - 1ULL - static_cast<uint64_t>(line[i]) + carryOut;
130 carryOut = sum / blockBase; line[i] = static_cast<block>(sum % blockBase);
131 }
132 return carryOut;
133 }
134 /* ----------------------------------------------------------------------- */
135
136public:
137 /* --------------------- @name Different constructors. ------------------- */
141 gpu constexpr Aeu() noexcept = default;
142
146 gpu constexpr ~Aeu() noexcept = default;
147
151 gpu constexpr Aeu(const Aeu& copy) noexcept = default;
152
157 gpu constexpr Aeu& operator=(const Aeu& other) = default;
158
165 template <typename Integral> requires (std::is_unsigned_v<Integral>)
166 gpu constexpr Aeu(Integral value) noexcept {
167 if(value != 0) {
168 uint64_t tValue = (value < 0 ? static_cast<uint64_t>(value * -1) : static_cast<uint64_t>(value));
169 for (std::size_t i = 0; i < blocksNumber; ++i) {
170 blocks[i] = static_cast<block>(tValue % blockBase);
171 tValue /= blockBase;
172 }
173 if(value < 0)
174 makeComplement(blocks);
175 } else
176 blocks = {};
177 }
178
185 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
186 gpu constexpr Aeu(const Char* data, std::size_t size) noexcept : Aeu {} {
187 if(size == 0) return;
188
189 constexpr const Char* characters = [] {
190 if constexpr (std::is_same_v<char, Char>) {
191 return "09aAfFoObBxX";
192 } else {
193 return L"09aAfFoObBxX";
194 }
195 } ();
196 std::size_t position = 0;
197
198 if constexpr (std::is_same_v<Char, char>) {
199 for(; position < size && !std::isalnum(data[position]); ++position) ;
200 } else {
201 for(; position < size && !std::iswalnum(data[position]); ++position) ;
202 }
203
204 if(position == size)
205 return;
206
207 const auto base = [&data, &size, &position, &characters] {
208 if (data[position] == characters[0] && size > position + 1) {
209 switch (data[position + 1]) {
210 case characters[8]:
211 case characters[9]:
212 position += 2; return 2u;
213 case characters[6]:
214 case characters[7]:
215 position += 2; return 8u;
216 case characters[10]:
217 case characters[11]:
218 position += 2; return 16u;
219 default:
220 return 10u;
221 }
222 } return 10u;
223 } ();
224
225 for(; position < size; ++position) {
226 const auto digit = [] (Char ch) {
227 if(characters[0] <= ch && ch <= characters[1])
228 return static_cast<unsigned>(ch) - static_cast<unsigned>(characters[0]);
229 if(characters[2] <= ch && ch <= characters[4])
230 return static_cast<unsigned>(ch) - static_cast<unsigned>(characters[2]) + 10u;
231 if(characters[3] <= ch && ch <= characters[5])
232 return static_cast<unsigned>(ch) - static_cast<unsigned>(characters[3]) + 10u;
233 return 99u;
234 } (data[position]);
235
236 if(digit < base) {
237 *this *= base;
238 *this += digit;
239 }
240 }
241 }
242
248 template <typename Char, std::size_t arrayLength> requires (arrayLength > 1 && (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>))
249 gpu constexpr Aeu(const Char (&literal)[arrayLength]) noexcept : Aeu(literal, arrayLength) {}
250
256 template <typename String, typename Char = typename String::value_type> requires (std::is_same_v<std::basic_string<Char>,
257 std::decay_t<String>> || std::is_same_v<std::basic_string_view<Char>, std::decay_t<String>>)
258 gpu constexpr Aeu(String&& stringView) noexcept : Aeu(stringView.data(), stringView.size()) {}
259
260 template <typename String, typename Char = typename String::value_type> requires (std::is_same_v<std::basic_string<Char>,
261 std::decay_t<String>> || std::is_same_v<std::basic_string_view<Char>, std::decay_t<String>>)
262 gpu constexpr Aeu(const String& stringView) noexcept : Aeu(stringView.data(), stringView.size()) {}
263
264#ifdef AESI_CRYPTOPP_INTEGRATION
269 constexpr Aeu(const CryptoPP::Integer& value): Aeu {} {
270 const auto byteCount = value.ByteCount();
271 if(byteCount * 8 > bitness)
272 throw std::invalid_argument("Accessed overflow on construction object from CryptoPP::Integer");
273 for(std::size_t i = 0; i < byteCount; ++i)
274 setByte(i, value.GetByte(i));
275 }
276#endif
277
278#ifdef AESI_GMP_INTEGRATION
283 constexpr Aeu(const mpz_class& value) : Aeu {} {
284 const auto bitLength = mpz_sizeinbase(value.get_mpz_t(), 2);
285 auto tBlocksNumber = 1 + (bitLength - 1) / sizeof(block) * 8;
286
287 std::basic_string<block> buffer (tBlocksNumber, 0u);
288 mpz_export(buffer.data(), &tBlocksNumber, -1, sizeof(block), -1, 0, value.get_mpz_t());
289
290 for (std::size_t i = 0; i < tBlocksNumber; ++i)
291 setBlock(i, buffer[i]);
292 }
293#endif
294 /* ----------------------------------------------------------------------- */
295
296
297 /* --------------------- @name Arithmetic operators. --------------------- */
298 /* ------------------------- @name Unary operators. -------------------------- */
304 [[nodiscard]]
305 gpu constexpr auto operator+() const noexcept -> Aeu { return *this; }
306
311 [[nodiscard]]
312 gpu constexpr auto operator-() const noexcept -> Aeu {
313 Aeu result = *this; makeComplement(result.blocks); return result;
314 }
315
320 gpu constexpr auto operator++() noexcept -> Aeu& {
321 for(std::size_t i = 0; i < blocksNumber; ++i) {
322 if(blocks[i] < blockMax) {
323 ++blocks[i];
324 break;
325 } else blocks[i] = 0u;
326 }
327 return *this;
328 }
329
334 gpu constexpr auto operator++(int) & noexcept -> Aeu { Aeu old = *this; operator++(); return old; }
335
340 gpu constexpr auto operator--() noexcept -> Aeu& {
341 for(std::size_t i = 0; i < blocksNumber; ++i) {
342 if(blocks[i] > 0u) {
343 --blocks[i]; break;
344 }
345 blocks[i] = blockMax;
346 }
347 return *this;
348 }
349
354 gpu constexpr auto operator--(int) & noexcept -> Aeu { Aeu old = *this; operator--(); return old; }
355 /* --------------------------------------------------------------------------- */
356
357
358 /* ------------------------ @name Addition operators. ------------------------ */
365 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned>) [[nodiscard]]
366 gpu constexpr friend auto operator+(const Aeu& addition, Unsigned addendum) noexcept -> Aeu {
367 Aeu result = addition; result += addendum; return result;
368 }
369
376 [[nodiscard]]
377 gpu constexpr friend auto operator+(const Aeu& addition, const Aeu& addendum) noexcept -> Aeu {
378 Aeu result = addition; result += addendum; return result;
379 }
380
387 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned>)
388 gpu constexpr friend auto operator+=(Aeu& addition, Unsigned addendum) noexcept -> Aeu& {
389 for(std::size_t i = 0; i < blocksNumber; ++i) {
390 const auto currentSum = static_cast<uint64_t>(addition.blocks[i]) + static_cast<uint64_t>(addendum);
391 addendum = currentSum / blockBase; addition.blocks[i] = currentSum % blockBase;
392 }
393 return addition;
394 }
395
402 gpu constexpr friend auto operator+=(Aeu& addition, const Aeu& addendum) noexcept -> Aeu& {
403 addLine(addition.blocks, addendum.blocks); return addition;
404 }
405 /* --------------------------------------------------------------------------- */
406
407
408 /* ----------------------- @name Subtraction operators. ---------------------- */
415 [[nodiscard]]
416 gpu constexpr friend auto operator-(const Aeu& subtraction, const Aeu& subtrahend) noexcept -> Aeu {
417 Aeu result = subtraction; result -= subtrahend; return result;
418 }
419
426 gpu constexpr friend auto operator-=(Aeu& subtraction, const Aeu& subtrahend) noexcept -> Aeu& {
427 return subtraction += -subtrahend;
428 }
429 /* --------------------------------------------------------------------------- */
430
431
432 /* --------------------- @name Multiplication operators. --------------------- */
439 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned>) [[nodiscard]]
440 gpu constexpr friend auto operator*(Aeu& multiplication, Unsigned factor) noexcept -> Aeu {
441 Aeu result = multiplication; result *= factor; return result;
442 }
443
450 [[nodiscard]]
451 gpu constexpr friend auto operator*(const Aeu& multiplication, const Aeu& factor) noexcept -> Aeu {
452 Aeu result = multiplication; result *= factor; return result;
453 }
454
462 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned>)
463 gpu constexpr friend auto operator*=(Aeu& multiplication, Unsigned factor) noexcept -> Aeu& {
464 if constexpr (std::is_same_v<Unsigned, uint64_t>) {
465 const auto longerLength = multiplication.filledBlocksNumber();
466 const auto smallerLength = (factor > blockMax ? 2UL : 1UL);
467 blockLine buffer {};
468
469 for(std::size_t i = 0; i < longerLength; ++i) {
470 const uint64_t tBlock = multiplication.blocks[i];
471 uint64_t carryOut = 0;
472
473 for(std::size_t j = 0; j < smallerLength && j < buffer.size() - i; ++j) {
474 const auto product = tBlock * (factor >> blockBitLength * j & 0x00'00'00'00'ff'ff'ff'ff) + carryOut;
475 const auto block = static_cast<uint64_t>(buffer[i + j]) + product % blockBase;
476 carryOut = product / blockBase + block / blockBase;
477 buffer[i + j] = block % blockBase;
478 }
479
480 if(smallerLength + i < buffer.size())
481 buffer[smallerLength + i] += carryOut;
482 }
483
484 multiplication.blocks = buffer;
485 return multiplication;
486 } else {
487 uint64_t carryOut = 0;
488 for (std::size_t i = 0; i < blocksNumber; ++i) {
489 const auto product = static_cast<uint64_t>(factor) * static_cast<uint64_t>(multiplication.blocks[i]) + carryOut;
490 multiplication.blocks[i] = product % blockBase; carryOut = product / blockBase;
491 }
492 return multiplication;
493 }
494 }
495
502 gpu constexpr friend auto operator*=(Aeu& multiplication, const Aeu& factor) noexcept -> Aeu& {
503 constexpr auto multiplyLines = [] (const blockLine& longerLine, const std::size_t longerLength,
504 const blockLine& smallerLine, const std::size_t smallerLength) {
505 blockLine buffer {};
506
507 for(std::size_t i = 0; i < longerLength; ++i) {
508 const uint64_t tBlock = longerLine[i];
509 uint64_t carryOut = 0;
510
511 for(std::size_t j = 0; j < smallerLength && j < buffer.size() - i; ++j) {
512 const auto product = tBlock * static_cast<uint64_t>(smallerLine[j]) + carryOut;
513 const auto block = static_cast<uint64_t>(buffer[i + j]) + product % blockBase;
514 carryOut = product / blockBase + block / blockBase;
515 buffer[i + j] = block % blockBase;
516 }
517
518 if(smallerLength < blocksNumber && smallerLength + i < buffer.size())
519 buffer[smallerLength + i] += carryOut;
520 }
521
522 return buffer;
523 };
524
525 const std::size_t thisLength = multiplication.filledBlocksNumber();
526 if(const std::size_t valueLength = factor.filledBlocksNumber(); thisLength > valueLength)
527 multiplication.blocks = multiplyLines(multiplication.blocks, thisLength, factor.blocks, valueLength);
528 else
529 multiplication.blocks = multiplyLines(factor.blocks, valueLength, multiplication.blocks, thisLength);
530
531 return multiplication;
532 }
533 /* --------------------------------------------------------------------------- */
534
535
536 /* ------------------------ @name Division operators. ------------------------ */
544 [[nodiscard]]
545 gpu constexpr friend auto operator/(const Aeu& division, const Aeu& divisor) noexcept -> Aeu {
546 Aeu quotient, _; divide(division, divisor, quotient, _); return quotient;
547 }
548
556 gpu constexpr friend auto operator/=(Aeu& division, const Aeu& divisor) noexcept -> Aeu& { return division = division / divisor; }
557 /* --------------------------------------------------------------------------- */
558
559
560 /* ------------------------- @name Modulo operators. ------------------------- */
567 [[nodiscard]]
568 gpu constexpr friend auto operator%(const Aeu& modulation, const Aeu& modulo) noexcept -> Aeu {
569 Aeu _, remainder; divide(modulation, modulo, _, remainder); return remainder;
570 }
571
578 gpu constexpr friend auto operator%=(Aeu& modulation, const Aeu& modulo) noexcept -> Aeu& {
579 return modulation = modulation % modulo;
580 }
581 /* --------------------------------------------------------------------------- */
582 /* ----------------------------------------------------------------------- */
583
584
585 /* ----------------------- @name Bitwise operators. ---------------------- */
590 [[nodiscard]]
591 gpu constexpr auto operator~() const noexcept -> Aeu {
592 Aeu result;
593 for(std::size_t i = 0; i < blocksNumber; ++i)
594 result.blocks[i] = ~blocks[i];
595 return result;
596 }
597
604 [[nodiscard]]
605 gpu constexpr friend auto operator^(const Aeu& left, const Aeu& right) noexcept -> Aeu {
606 Aeu result = left; result ^= right; return result;
607 }
608
615 gpu constexpr friend auto operator^=(Aeu& left, const Aeu& right) noexcept -> Aeu& {
616 for(std::size_t i = 0; i < blocksNumber; ++i)
617 left.blocks[i] ^= right.blocks[i];
618 return left;
619 }
620
627 [[nodiscard]]
628 gpu constexpr friend auto operator&(const Aeu& left, const Aeu& right) noexcept -> Aeu {
629 Aeu result = left; result &= right; return result;
630 }
631
638 gpu constexpr friend auto operator&=(Aeu& left, const Aeu& right) noexcept -> Aeu& {
639 for(std::size_t i = 0; i < blocksNumber; ++i)
640 left.blocks[i] &= right.blocks[i];
641 return left;
642 }
643
650 [[nodiscard]]
651 gpu constexpr friend auto operator|(const Aeu& left, const Aeu& right) noexcept -> Aeu {
652 Aeu result = left; result |= right; return result;
653 }
654
661 gpu constexpr friend auto operator|=(Aeu& left, const Aeu& right) noexcept -> Aeu& {
662 for(std::size_t i = 0; i < blocksNumber; ++i)
663 left.blocks[i] |= right.blocks[i];
664 return left;
665 }
666
674 template <typename Unsigned> requires (std::is_integral_v<Unsigned> && std::is_unsigned_v<Unsigned>) [[nodiscard]]
675 gpu constexpr friend auto operator<<(const Aeu& value, Unsigned bitShift) noexcept -> Aeu {
676 Aeu result = value; result <<= bitShift; return result;
677 }
678
686 template <typename Unsigned> requires (std::is_integral_v<Unsigned> && std::is_unsigned_v<Unsigned>)
687 gpu constexpr friend auto operator<<=(Aeu& value, Unsigned bitShift) noexcept -> Aeu& {
688 if(bitShift >= bitness || bitShift == 0) return value;
689
690 const std::size_t quotient = bitShift / blockBitLength, remainder = bitShift % blockBitLength;
691 const block stamp = (1UL << (blockBitLength - remainder)) - 1;
692
693 for (long long i = blocksNumber - 1; i >= (quotient + (remainder ? 1 : 0)); --i)
694 value.blocks[i] = (value.blocks[i - quotient] & stamp) << remainder
695 | ((value.blocks[i - quotient - (remainder ? 1 : 0)] & ~stamp) >> (blockBitLength - remainder) % blockBitLength);
696
697 value.blocks[quotient] = (value.blocks[0] & stamp) << remainder;
698
699 for (std::size_t i = 0; i < quotient; ++i)
700 value.blocks[i] = 0;
701 return value;
702 }
703
711 template <typename Unsigned> requires (std::is_integral_v<Unsigned> && std::is_unsigned_v<Unsigned>) [[nodiscard]]
712 gpu constexpr friend auto operator>>(const Aeu& value, Unsigned bitShift) noexcept -> Aeu {
713 Aeu result = value; result >>= bitShift; return result;
714 }
715
723 template <typename Unsigned> requires (std::is_integral_v<Unsigned> && std::is_unsigned_v<Unsigned>)
724 gpu constexpr friend auto operator>>=(Aeu& value, Unsigned bitShift) noexcept -> Aeu& {
725 if(bitShift >= bitness || bitShift == 0) return value;
726
727 const std::size_t quotient = bitShift / blockBitLength, remainder = bitShift % blockBitLength;
728 const block stamp = (1UL << remainder) - 1;
729
730 for(std::size_t i = 0; i < blocksNumber - (quotient + (remainder ? 1 : 0)); ++i)
731 value.blocks[i] = ((value.blocks[i + quotient + (remainder ? 1 : 0)] & stamp) << (blockBitLength - remainder) % blockBitLength) | (value.blocks[i + quotient] & ~stamp) >> remainder;
732
733 value.blocks[blocksNumber - 1 - quotient] = (value.blocks[blocksNumber - 1] & ~stamp) >> remainder;
734
735 for(long long i = blocksNumber - quotient; i < blocksNumber; ++i)
736 value.blocks[i] = 0;
737 return value;
738 }
739 /* ----------------------------------------------------------------------- */
740
741
742 /* --------------------- @name Comparison operators. --------------------- */
743 /* ------------------------ @name Equality operators. ------------------------ */
750 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned> && sizeof(Unsigned) < 8)
751 gpu constexpr friend auto operator==(const Aeu& our, Unsigned other) noexcept -> bool {
752 return our.filledBlocksNumber() <= 1 && static_cast<block>(other) == our.blocks[0];
753 }
754 gpu constexpr friend auto operator==(const Aeu& our, uint64_t other) noexcept -> bool {
755 return our.filledBlocksNumber() <= 2 && (static_cast<uint64_t>(our.blocks[1]) << blockBitLength | static_cast<uint64_t>(our.blocks[0])) == other;
756 }
757
764 template <std::size_t otherBitness>
765 gpu constexpr friend auto operator==(const Aeu& our, const Aeu<otherBitness>& other) noexcept -> bool {
766 return our.compareTo(other) == Comparison::equal;
767 }
768 /* --------------------------------------------------------------------------- */
769
770
771 /* ----------------------- @name Comparison operators. ----------------------- */
778 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned> && sizeof(Unsigned) < 8) [[nodiscard]]
779 gpu constexpr auto compareTo(Unsigned other) const noexcept -> Comparison {
780 using enum Comparison;
781
782 if(filledBlocksNumber() > 1) return greater;
783 const auto cmp = static_cast<block>(other);
784
785 if(blocks[0] > cmp)
786 return greater;
787
788 if(blocks[0] < cmp)
789 return less;
790
791 return equal;
792 }
793
800 [[nodiscard]]
801 gpu constexpr auto compareTo(uint64_t other) const noexcept -> Comparison {
802 using enum Comparison;
803 if(filledBlocksNumber() > 2) return greater;
804 const auto base = (static_cast<uint64_t>(blocks[1]) << blockBitLength) | static_cast<uint64_t>(blocks[0]);
805 if(base > other)
806 return greater; else if(base < other) return less; else return equal;
807 }
808
815 template <std::size_t otherBitness = bitness> /*requires (otherBitness != bitness)*/ [[nodiscard]]
816 gpu constexpr auto compareTo(const Aeu<otherBitness>& other) const noexcept -> Comparison {
817 using enum Comparison;
818
819 const auto lowerBlockBorder = (blocksNumber < other.totalBlocksNumber() ? blocksNumber : other.totalBlocksNumber());
820 for(long long i = lowerBlockBorder - 1; i >= 0; --i) {
821 const block thisBlock = blocks[i], otherBlock = other.getBlock(i);
822 if(thisBlock != otherBlock)
823 return (thisBlock > otherBlock ? greater : less);
824 }
825
826 if constexpr (otherBitness != blocksNumber * blockBitLength) {
827 using enum Comparison;
828 if (other.totalBlocksNumber() > blocksNumber) {
829 for (long long i = other.totalBlocksNumber() - 1; i > lowerBlockBorder - 1; --i)
830 if (other.getBlock(i) != 0)
831 return less;
832 } else if (blocksNumber > other.totalBlocksNumber()) {
833 for (long long i = blocksNumber - 1; i > lowerBlockBorder - 1; --i)
834 if (blocks[i] != 0)
835 return greater;
836 }
837 }
838
839 return equal;
840 }
841 /* --------------------------------------------------------------------------- */
842
843
844 /* ------------------------ @name Spaceship operators. ----------------------- */
845#if (defined(__CUDACC__) || __cplusplus < 202002L || defined (PRE_CPP_20)) && !defined DOXYGEN_SKIP
849 gpu constexpr auto operator!=(const Aeu& value) const noexcept -> bool { return !this->operator==(value); }
850 gpu constexpr auto operator<(const Aeu& value) const noexcept -> bool { return this->compareTo(value) == Comparison::less; }
851 gpu constexpr auto operator<=(const Aeu& value) const noexcept -> bool { return !this->operator>(value); }
852 gpu constexpr auto operator>(const Aeu& value) const noexcept -> bool { return this->compareTo(value) == Comparison::greater; }
853 gpu constexpr auto operator>=(const Aeu& value) const noexcept -> bool { return !this->operator<(value); }
854#else
861 gpu constexpr auto operator<=>(const Aeu& other) const noexcept -> std::strong_ordering {
862 switch(this->compareTo(other)) {
863 using enum Comparison;
864 case less:
865 return std::strong_ordering::less;
866 case greater:
867 return std::strong_ordering::greater;
868 case equal:
869 return std::strong_ordering::equal;
870 default:
871 return std::strong_ordering::equivalent;
872 }
873 };
874
881 template <typename Unsigned>
882 gpu constexpr auto operator<=>(const Unsigned& other) const noexcept -> std::strong_ordering {
883 switch(this->compareTo(other)) {
884 using enum Comparison;
885 case less:
886 return std::strong_ordering::less;
887 case greater:
888 return std::strong_ordering::greater;
889 case equal:
890 return std::strong_ordering::equal;
891 default:
892 return std::strong_ordering::equivalent;
893 }
894 };
895#endif
896 /* --------------------------------------------------------------------------- */
897 /* ----------------------------------------------------------------------- */
898
899
900 /* ---------------------- @name Supporting methods. ---------------------- */
907 gpu constexpr auto setBit(std::size_t index, bool bit) noexcept -> void {
908#ifndef AESI_UNSAFE
909 if(index >= bitness) return;
910#endif
911 const std::size_t blockNumber = index / blockBitLength, bitNumber = index % blockBitLength;
912 assert(blockNumber < blocksNumber && bitNumber < blockBitLength);
913 if(bit)
914 blocks[blockNumber] |= (1U << bitNumber);
915 else
916 blocks[blockNumber] &= (~(1U << bitNumber));
917 }
918
925 [[nodiscard]]
926 gpu constexpr auto getBit(std::size_t index) const noexcept -> bool {
927#ifndef AESI_UNSAFE
928 if(index >= bitness) return false;
929#endif
930 const std::size_t blockNumber = index / blockBitLength, bitNumber = index % blockBitLength;
931 assert(blockNumber < blocksNumber && bitNumber < blockBitLength);
932 return blocks[blockNumber] & (1U << bitNumber);
933 }
934
941 gpu constexpr auto setByte(std::size_t index, byte byte) noexcept -> void {
942#ifndef AESI_UNSAFE
943 if(index > blocksNumber * sizeof(block)) return;
944#endif
945 const std::size_t blockNumber = index / sizeof(block), byteInBlock = index % sizeof(block), shift = byteInBlock * bitsInByte;
946 assert(blockNumber < blocksNumber && byteInBlock < sizeof(block));
947 blocks[blockNumber] &= ~(0xffU << shift); blocks[blockNumber] |= static_cast<block>(byte) << shift;
948 }
949
956 [[nodiscard]]
957 gpu constexpr auto getByte(std::size_t index) const noexcept -> byte {
958#ifndef AESI_UNSAFE
959 if(index > blocksNumber * sizeof(block)) return 0;
960#endif
961 const std::size_t blockNumber = index / sizeof(block), byteInBlock = index % sizeof(block), shift = byteInBlock * bitsInByte;
962 assert(blockNumber < blocksNumber && byteInBlock < sizeof(block));
963 return (blocks[blockNumber] & (0xffU << shift)) >> shift;
964 }
965
972 gpu constexpr auto setBlock(std::size_t index, block block) noexcept -> void {
973#ifndef AESI_UNSAFE
974 if(index >= blocksNumber) return;
975#endif
976 blocks[index] = block;
977 }
978
985 [[nodiscard]]
986 gpu constexpr auto getBlock(std::size_t index) const noexcept -> block {
987#ifndef AESI_UNSAFE
988 if(index >= blocksNumber) return block();
989#endif
990 return blocks[index];
991 }
992
997 [[nodiscard]]
998 gpu constexpr auto byteCount() const noexcept -> std::size_t {
999 std::size_t lastBlock = blocksNumber - 1;
1000 for(; lastBlock > 0 && blocks[lastBlock] == 0; --lastBlock)
1001 ;
1002
1003 for(int8_t byteN = sizeof(block) - 1; byteN >= 0; --byteN) {
1004 if((blocks[lastBlock] & (0xffU << (byteN * bitsInByte))) >> (byteN * bitsInByte))
1005 return lastBlock * sizeof(block) + byteN + 1;
1006 }
1007 return lastBlock * sizeof(block);
1008 }
1009
1014 [[nodiscard]]
1015 gpu constexpr auto bitCount() const noexcept -> std::size_t {
1016 std::size_t lastBlock = blocksNumber - 1;
1017 for(; lastBlock > 0 && blocks[lastBlock] == 0; --lastBlock)
1018 ;
1019
1020 for(int8_t byteN = sizeof(block) - 1; byteN >= 0; --byteN) {
1021 const auto byte = (blocks[lastBlock] & (0xffU << (byteN * bitsInByte))) >> (byteN * bitsInByte);
1022 if(!byte) continue;
1023
1024 for(int8_t bitN = bitsInByte - 1; bitN >= 0; --bitN) {
1025 if((byte & (0x1u << bitN)) >> bitN)
1026 return (lastBlock * sizeof(block) + byteN) * bitsInByte + bitN + 1;
1027 }
1028 return ((lastBlock - 1) * sizeof(block) + byteN) * bitsInByte;
1029 }
1030 return lastBlock * sizeof(block);
1031 }
1032
1037 [[nodiscard]]
1038 gpu constexpr auto isOdd() const noexcept -> bool { return (0x1 & blocks[0]) == 1; }
1039
1044 [[nodiscard]]
1045 gpu constexpr auto isEven() const noexcept -> bool { return (0x1 & blocks[0]) == 0; }
1046
1051 [[nodiscard]]
1052 gpu constexpr auto isZero() const noexcept -> bool { return filledBlocksNumber() == 0; }
1053
1058 [[nodiscard]]
1059 gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t {
1060 for(long long i = blocksNumber - 1; i >= 0; --i)
1061 if(blocks[i]) return i + 1;
1062 return 0;
1063 }
1064
1069 [[nodiscard]]
1070 gpu static constexpr auto getBitness() noexcept -> std::size_t { return bitness; }
1071
1076 [[nodiscard]]
1077 gpu static constexpr auto totalBlocksNumber() noexcept -> std::size_t { return blocksNumber; }
1078
1083 gpu constexpr auto swap(Aeu& other) noexcept -> void {
1084 Aeu t = other; other.operator=(*this); this->operator=(t);
1085 }
1086 /* ----------------------------------------------------------------------- */
1087
1088
1089 /* -------------- @name Public arithmetic and number theory. ------------- */
1098 gpu static constexpr auto divide(const Aeu& number, const Aeu& divisor, Aeu& quotient, Aeu& remainder) noexcept -> void {
1099 const auto ratio = number.compareTo(divisor);
1100
1101 quotient = Aeu {}; remainder = Aeu {};
1102
1103 if(ratio == Comparison::greater) {
1104 const auto bitsUsed = number.filledBlocksNumber() * blockBitLength;
1105 for(long long i = bitsUsed - 1; i >= 0; --i) {
1106 remainder <<= 1u;
1107 remainder.setBit(0, number.getBit(i));
1108
1109 if(remainder >= divisor) {
1110 remainder -= divisor;
1111 quotient.setBit(i, true);
1112 }
1113 }
1114 } else if(ratio == Comparison::less)
1115 remainder = number; else quotient = 1u;
1116 }
1117
1124 [[nodiscard]]
1125 gpu static constexpr auto divide(const Aeu& number, const Aeu& divisor) noexcept -> pair<Aeu, Aeu> {
1126 pair<Aeu, Aeu> results; divide(number, divisor, results.first, results.second); return results;
1127 }
1128
1138 gpu static constexpr auto gcd(const Aeu& first, const Aeu& second, Aeu& bezoutX, Aeu& bezoutY) noexcept -> Aeu {
1139 Aeu gcd, quotient, remainder;
1140
1141 const auto ratio = first.compareTo(second);
1142 if(ratio == Comparison::greater) {
1143 gcd = second;
1144 divide(first, second, quotient, remainder);
1145 } else {
1146 gcd = first;
1147 divide(second, first, quotient, remainder);
1148 }
1149
1150 bezoutX = 0u; bezoutY = 1u;
1151 for(Aeu tX = 1u, tY = 0u; remainder != 0u; ) {
1152 Aeu tGcd = gcd; gcd = remainder;
1153
1154 Aeu t = bezoutX; bezoutX = tX - quotient * bezoutX; tX = t;
1155 t = bezoutY; bezoutY = tY - quotient * bezoutY; tY = t;
1156
1157 divide(tGcd, gcd, quotient, remainder);
1158 }
1159
1160 if(ratio != Comparison::greater)
1161 bezoutX.swap(bezoutY);
1162
1163 return gcd;
1164 }
1165
1173 gpu static constexpr auto gcd(const Aeu& first, const Aeu& second) noexcept -> Aeu {
1174 Aeu gcd, quotient, remainder;
1175
1176 const auto ratio = first.compareTo(second);
1177 if(ratio == Comparison::greater) {
1178 gcd = second;
1179 divide(first, second, quotient, remainder);
1180 } else {
1181 gcd = first;
1182 divide(second, first, quotient, remainder);
1183 }
1184
1185 for(Aeu tX = 1u, tY = 0u; remainder != 0u; ) {
1186 Aeu tGcd = gcd; gcd = remainder;
1187 divide(tGcd, gcd, quotient, remainder);
1188 }
1189
1190 return gcd;
1191 }
1192
1199 [[nodiscard]]
1200 gpu static constexpr auto lcm(const Aeu& first, const Aeu& second) noexcept -> Aeu { return first / gcd(first, second) * second; }
1201
1211 template <std::size_t powerBitness = bitness> [[nodiscard]]
1212 gpu static constexpr auto powm(const Aeu& base, const Aeu<powerBitness>& power, const Aeu& modulo) noexcept -> Aeu {
1213 if(base == 1u)
1214 return base;
1215 if(base == 0u)
1216 return { 1u };
1217
1218 Aeu output = 1u;
1219 auto [_, b] = divide(base, modulo);
1220
1221 for(unsigned iteration = 0; power.filledBlocksNumber() * blockBitLength != iteration; iteration++) {
1222 if(power.getBit(iteration)) {
1223 const auto [quotient, remainder] = divide(output * b, modulo);
1224 output = remainder;
1225 }
1226
1227 const auto [quotient, remainder] = divide(b * b, modulo);
1228 b = remainder;
1229 }
1230
1231 return output;
1232 }
1233
1234 [[nodiscard]]
1235 gpu static constexpr auto powm(const Aeu& base, const Aeu& power, const Aeu& mod) noexcept -> Aeu {
1236 Aeu output = 1u;
1237 auto [_, b] = divide(base, mod);
1238
1239 for(std::size_t iteration = 0; power.filledBlocksNumber() * blockBitLength != iteration; iteration++) {
1240 if(power.getBit(iteration)) {
1241 const auto [quotient, remainder] = divide(output * b, mod);
1242 output = remainder;
1243 }
1244
1245 const auto [quotient, remainder] = divide(b * b, mod);
1246 b = remainder;
1247 }
1248
1249 return output;
1250 }
1251
1258 [[nodiscard]]
1259 gpu static constexpr auto power2(std::size_t power) noexcept -> Aeu { Aeu result {}; result.setBit(power, true); return result; }
1260
1266 [[nodiscard]]
1267 gpu constexpr auto squareRoot() const noexcept -> Aeu {
1268 Aeu x, y = power2((bitCount() + 1) / 2);
1269
1270 do {
1271 x = y;
1272 y = (x + *this / x) >> 1u;
1273 } while (y < x);
1274
1275 return x;
1276 }
1277 /* ----------------------------------------------------------------------- */
1278
1279
1280 /* ----------------- @name Public input-output operators. ---------------- */
1291 template <byte base, typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t> && (base == 2 || base == 8 || base == 10 || base == 16))
1292 gpu constexpr auto getString(Char* const buffer, std::size_t bufferSize, bool showBase = false, bool hexUppercase = false) const noexcept -> std::size_t {
1293 if(bufferSize < 2) return 0;
1294
1295 std::size_t position = 0;
1296
1297 if (showBase && bufferSize > 3) {
1298 if constexpr (base == 2) {
1299 if constexpr (std::is_same_v<Char, char>) {
1300 buffer[0] = '0'; buffer[1] = 'b';
1301 } else {
1302 buffer[0] = L'0'; buffer[1] = L'b';
1303 }
1304 position += 2;
1305 } else if constexpr (base == 8) {
1306 if constexpr (std::is_same_v<Char, char>) {
1307 buffer[0] = '0'; buffer[1] = 'o';
1308 } else {
1309 buffer[0] = L'0'; buffer[1] = L'o';
1310 }
1311 position += 2;
1312 } else if constexpr (base == 16) {
1313 if constexpr (std::is_same_v<Char, char>) {
1314 buffer[0] = '0'; buffer[1] = 'x';
1315 } else {
1316 buffer[0] = L'0'; buffer[1] = L'x';
1317 }
1318 position += 2;
1319 }
1320 }
1321
1322 if(isZero()) {
1323 buffer[position++] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; }}();
1324 return position;
1325 }
1326
1327 if constexpr (base == 16) {
1328 long long iter = blocks.size() - 1;
1329 for (; blocks[iter] == 0 && iter >= 0; --iter)
1330 ;
1331
1332 if constexpr (std::is_same_v<Char, char>) {
1333 position += snprintf(buffer + position, bufferSize - position, (hexUppercase ? "%X" : "%x"), blocks[iter--]);
1334 for (; iter >= 0; --iter)
1335 position += snprintf(buffer + position, bufferSize - position, (hexUppercase ? "%08X" : "%08x"), blocks[iter]);
1336 } else {
1337 position += swprintf(buffer + position, bufferSize - position, (hexUppercase ? L"%X" : L"%x"), blocks[iter--]);
1338 for (; iter >= 0; --iter)
1339 position += swprintf(buffer + position, bufferSize - position, (hexUppercase ? L"%08X" : L"%08x"), blocks[iter]);
1340 }
1341 } else {
1342 const auto startPosition = position;
1343
1344 Aeu copy = *this;
1345 while (!copy.isZero() && position < bufferSize) {
1346 auto [quotient, remainder] = divide(copy, base);
1347 if constexpr (std::is_same_v<Char, char>) {
1348 buffer[position++] = '0' + remainder.template integralCast<byte>();
1349 } else {
1350 buffer[position++] = L'0' + remainder.template integralCast<byte>();
1351 }
1352 copy = quotient;
1353 }
1354 const auto digitsTotal = position - startPosition;
1355 for (std::size_t i = 0; i * 2 < digitsTotal; ++i) {
1356 Char t = buffer[startPosition + i];
1357 buffer[startPosition + i] = buffer[startPosition + digitsTotal - 1 - i];
1358 buffer[startPosition + digitsTotal - 1 - i] = t;
1359 }
1360 }
1361 buffer[position++] = Char {};
1362 return position;
1363 }
1364
1376 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1377 friend constexpr auto operator<<(std::basic_ostream<Char>& os, const Aeu& number) -> std::basic_ostream<Char>& {
1378 auto flags = os.flags();
1379
1380 const auto base = [] (long baseField, std::basic_ostream<Char>& ss, bool showbase) {
1381 auto tBase = (baseField == std::ios::hex ? 16u : (baseField == std::ios::oct ? 8u : 10u));
1382 if(showbase && tBase != 10)
1383 ss << [&tBase] {
1384 if constexpr (std::is_same_v<Char, char>) {
1385 return tBase == 8 ? "0o" : "0x";
1386 } else {
1387 return tBase == 8 ? L"0o" : L"0x";
1388 }
1389 } () << std::noshowbase ;
1390 return tBase;
1391 } (flags & std::ios::basefield, os, flags & std::ios::showbase);
1392
1393 if(number.isZero())
1394 return os << '0';
1395
1396 if(base == 16) {
1397 long long iter = number.blocks.size() - 1;
1398 for(; number.blocks[iter] == 0 && iter >= 0; --iter)
1399 ;
1400
1401 os << number.blocks[iter--];
1402 for (; iter >= 0; --iter) {
1403 os.fill([] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ());
1404 os.width(8); os << std::right << number.blocks[iter];
1405 }
1406 } else {
1407 /* Well, here we use a pre-calculated magic number to ratio the length of numbers in decimal or octal notation according to bitness.
1408 * * It is 2.95-98 for octal and 3.2 for decimal. */
1409 constexpr auto bufferSize = static_cast<std::size_t>(static_cast<double>(bitness) / 2.95);
1410 Char buffer [bufferSize] {}; std::size_t filled = 0;
1411
1412 Aeu copy = number;
1413 while(!copy.isZero() && filled < bufferSize) {
1414 const auto [quotient, remainder] = divide(copy, base);
1415 buffer[filled++] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } () + remainder.template integralCast<byte>();
1416 copy = quotient;
1417 }
1418
1419 for(; filled > 0; --filled)
1420 os << buffer[filled - 1];
1421 }
1422
1423 return os;
1424 }
1425
1426
1435 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1436 constexpr auto readBinary(std::basic_istream<Char>& is, bool bigEndian = true) -> void {
1437 blocks = {};
1438 if(bigEndian) {
1439 for(auto it = blocks.rbegin(); it != blocks.rend(); ++it)
1440 if(!is.read(reinterpret_cast<char*>(&*it), sizeof(block))) break;
1441 } else {
1442 for(auto& tBlock: blocks)
1443 if(!is.read(reinterpret_cast<char*>(&tBlock), sizeof(block))) break;
1444 }
1445 }
1446
1447
1454 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1455 constexpr auto writeBinary(std::basic_ostream<Char>& os, bool bigEndian = true) const noexcept -> void {
1456 if(bigEndian) {
1457 for(auto it = blocks.rbegin(); it != blocks.rend(); ++it)
1458 if(!os.write(reinterpret_cast<const char*>(&*it), sizeof(block))) break;
1459 } else {
1460 for(auto& block: blocks)
1461 if(!os.write(reinterpret_cast<const char*>(&block), sizeof(block))) break;
1462 }
1463 }
1464 /* ----------------------------------------------------------------------- */
1465
1466
1467 /* -------------------- @name Public casting operators. ------------------ */
1473 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
1474 gpu constexpr auto integralCast() const noexcept -> Integral {
1475 const uint64_t value = (static_cast<uint64_t>(blocks[1]) << blockBitLength) | static_cast<uint64_t>(blocks[0]);
1476 return static_cast<Integral>(value);
1477 }
1478
1487 template <std::size_t newBitness> requires (newBitness != bitness) [[nodiscard]]
1488 gpu constexpr auto precisionCast() const noexcept -> Aeu<newBitness> {
1489 Aeu<newBitness> result {};
1490
1491 const std::size_t blockBoarder = (newBitness > bitness ? Aeu<bitness>::totalBlocksNumber() : Aeu<newBitness>::totalBlocksNumber());
1492 for(std::size_t blockIdx = 0; blockIdx < blockBoarder; ++blockIdx)
1493 result.setBlock(blockIdx, getBlock(blockIdx));
1494
1495 return result;
1496 }
1497 /* ----------------------------------------------------------------------- */
1498
1499
1500#if defined __CUDACC__
1501 /* ------------------- @name Atomic-like CUDA operators. ----------------- */
1508 __device__ constexpr auto tryAtomicSet(const Aeu& value) noexcept -> void {
1509 for(std::size_t i = 0; i < blocksNumber; ++i)
1510 atomicExch(&blocks[i], value.blocks[i]);
1511 }
1512
1519 __device__ constexpr auto tryAtomicExchange(const Aeu& value) noexcept -> void {
1520 for(std::size_t i = 0; i < blocksNumber; ++i)
1521 atomicExch(&value.blocks[i], atomicExch(&blocks[i], value.blocks[i]));
1522 }
1523 /* ----------------------------------------------------------------------- */
1524#endif
1525};
1526
1527/* -------------------------------------------- @name Type-definitions ------------------------------------------- */
1532
1537
1542
1547
1552
1557
1562
1567
1572
1577
1582/* ---------------------------------------------------------------------------------------------------------------- */
1583
1584/* ------------------------------------------ @name Integral conversions ----------------------------------------- */
1591template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1592gpu constexpr auto operator+(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) + value; }
1593
1600template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1601gpu constexpr auto operator-(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) - value; }
1602
1609template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1610gpu constexpr auto operator*(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) * value; }
1611
1618template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1619gpu constexpr auto operator/(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) / value; }
1620
1627template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1628gpu constexpr auto operator%(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) % value; }
1629
1636template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1637gpu constexpr auto operator^(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) ^ value; }
1638
1645template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1646gpu constexpr auto operator&(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) & value; }
1647
1654template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1655gpu constexpr auto operator|(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) | value; }
1656/* ---------------------------------------------------------------------------------------------------------------- */
1657
1658#endif //AEU_MULTIPRECISION
Long precision unsigned integer.
Definition Aeu.h:83
static gpu constexpr auto gcd(const Aeu &first, const Aeu &second, Aeu &bezoutX, Aeu &bezoutY) noexcept -> Aeu
Extended Euclidean algorithm for greatest common divisor.
Definition Aeu.h:1138
gpu constexpr auto operator<=>(const Aeu &other) const noexcept -> std::strong_ordering
Three-way comparison operator.
Definition Aeu.h:861
gpu constexpr friend auto operator|=(Aeu &left, const Aeu &right) noexcept -> Aeu &
Assignment bitwise OR operator.
Definition Aeu.h:661
gpu constexpr auto bitCount() const noexcept -> std::size_t
Get amount of non-empty bits in number right to left.
Definition Aeu.h:1015
gpu constexpr friend auto operator&(const Aeu &left, const Aeu &right) noexcept -> Aeu
Bitwise AND operator.
Definition Aeu.h:628
gpu constexpr auto compareTo(Unsigned other) const noexcept -> Comparison
Internal comparison operator for built-in integral types uint8_t, uint16_t, uint32_t.
Definition Aeu.h:779
gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t
Get number of non-empty blocks inside object starting from the right.
Definition Aeu.h:1059
gpu constexpr auto operator+() const noexcept -> Aeu
Unary plus operator.
Definition Aeu.h:305
gpu constexpr auto getString(Char *const buffer, std::size_t bufferSize, bool showBase=false, bool hexUppercase=false) const noexcept -> std::size_t
Character buffer output operator.
Definition Aeu.h:1292
gpu constexpr friend auto operator/(const Aeu &division, const Aeu &divisor) noexcept -> Aeu
Division operator.
Definition Aeu.h:545
static gpu constexpr auto power2(std::size_t power) noexcept -> Aeu
Fast exponentiation for powers of 2.
Definition Aeu.h:1259
static gpu constexpr auto gcd(const Aeu &first, const Aeu &second) noexcept -> Aeu
Greatest common divisor.
Definition Aeu.h:1173
gpu constexpr auto isEven() const noexcept -> bool
Check whether number is even.
Definition Aeu.h:1045
gpu constexpr auto operator~() const noexcept -> Aeu
Bitwise complement operator.
Definition Aeu.h:591
gpu constexpr auto setByte(std::size_t index, byte byte) noexcept -> void
Set byte in number by index starting from the right.
Definition Aeu.h:941
gpu constexpr friend auto operator+(const Aeu &addition, const Aeu &addendum) noexcept -> Aeu
Addition operator.
Definition Aeu.h:377
gpu constexpr friend auto operator==(const Aeu &our, const Aeu< otherBitness > &other) noexcept -> bool
Templated Equality check operator for numbers of different precision.
Definition Aeu.h:765
gpu constexpr Aeu(String &&stringView) noexcept
String or string-view based constructor.
Definition Aeu.h:258
gpu constexpr friend auto operator%(const Aeu &modulation, const Aeu &modulo) noexcept -> Aeu
Modulo operator.
Definition Aeu.h:568
gpu constexpr auto byteCount() const noexcept -> std::size_t
Get amount of non-empty bytes in number right to left.
Definition Aeu.h:998
gpu constexpr auto setBlock(std::size_t index, block block) noexcept -> void
Set block in number by index starting from the right.
Definition Aeu.h:972
gpu constexpr friend auto operator&=(Aeu &left, const Aeu &right) noexcept -> Aeu &
Assignment bitwise AND operator.
Definition Aeu.h:638
gpu constexpr auto getByte(std::size_t index) const noexcept -> byte
Get byte in number by index starting from the right.
Definition Aeu.h:957
gpu constexpr Aeu(const Char(&literal)[arrayLength]) noexcept
C-style string literal constructor.
Definition Aeu.h:249
gpu constexpr auto operator--(int) &noexcept -> Aeu
Postfix decrement.
Definition Aeu.h:354
static gpu constexpr auto powm(const Aeu &base, const Aeu< powerBitness > &power, const Aeu &modulo) noexcept -> Aeu
Exponentiation by modulo.
Definition Aeu.h:1212
gpu constexpr auto integralCast() const noexcept -> Integral
Integral type cast operator for built-in types.
Definition Aeu.h:1474
gpu constexpr friend auto operator-=(Aeu &subtraction, const Aeu &subtrahend) noexcept -> Aeu &
Assignment subtraction operator.
Definition Aeu.h:426
gpu constexpr auto isOdd() const noexcept -> bool
Check whether number is odd.
Definition Aeu.h:1038
gpu constexpr friend auto operator^=(Aeu &left, const Aeu &right) noexcept -> Aeu &
Assignment bitwise XOR operator.
Definition Aeu.h:615
constexpr auto writeBinary(std::basic_ostream< Char > &os, bool bigEndian=true) const noexcept -> void
STD stream binary writing operator.
Definition Aeu.h:1455
static gpu constexpr auto divide(const Aeu &number, const Aeu &divisor) noexcept -> pair< Aeu, Aeu >
Integer division. Returns results by value.
Definition Aeu.h:1125
gpu constexpr auto swap(Aeu &other) noexcept -> void
Make swap between two objects.
Definition Aeu.h:1083
static gpu constexpr auto divide(const Aeu &number, const Aeu &divisor, Aeu &quotient, Aeu &remainder) noexcept -> void
Integer division. Returns results by reference.
Definition Aeu.h:1098
gpu constexpr auto operator++(int) &noexcept -> Aeu
Postfix increment.
Definition Aeu.h:334
static gpu constexpr auto getBitness() noexcept -> std::size_t
Get number's precision.
Definition Aeu.h:1070
gpu constexpr friend auto operator|(const Aeu &left, const Aeu &right) noexcept -> Aeu
Bitwise OR operator.
Definition Aeu.h:651
gpu constexpr friend auto operator^(const Aeu &left, const Aeu &right) noexcept -> Aeu
Bitwise XOR operator.
Definition Aeu.h:605
gpu constexpr auto setBit(std::size_t index, bool bit) noexcept -> void
Set a bit in number by index starting from the right.
Definition Aeu.h:907
gpu constexpr auto precisionCast() const noexcept -> Aeu< newBitness >
Precision cast operator.
Definition Aeu.h:1488
static gpu constexpr auto totalBlocksNumber() noexcept -> std::size_t
Get the number of blocks (length of array of uint32_t integers) inside object.
Definition Aeu.h:1077
gpu constexpr auto isZero() const noexcept -> bool
Check whether number is zero.
Definition Aeu.h:1052
gpu constexpr auto operator<=>(const Unsigned &other) const noexcept -> std::strong_ordering
Three-way comparison operator for numbers of different precision and built-in integral types.
Definition Aeu.h:882
gpu constexpr friend auto operator%=(Aeu &modulation, const Aeu &modulo) noexcept -> Aeu &
Assignment modulo operator.
Definition Aeu.h:578
gpu constexpr friend auto operator/=(Aeu &division, const Aeu &divisor) noexcept -> Aeu &
Assignment division operator.
Definition Aeu.h:556
gpu constexpr auto operator--() noexcept -> Aeu &
Prefix decrement.
Definition Aeu.h:340
constexpr auto readBinary(std::basic_istream< Char > &is, bool bigEndian=true) -> void
STD stream binary reading operator.
Definition Aeu.h:1436
gpu constexpr Aeu(const Char *data, std::size_t size) noexcept
Pointer-based character constructor.
Definition Aeu.h:186
gpu constexpr auto compareTo(uint64_t other) const noexcept -> Comparison
Internal comparison operator for type uint64_t.
Definition Aeu.h:801
gpu constexpr friend auto operator*=(Aeu &multiplication, const Aeu &factor) noexcept -> Aeu &
Assignment multiplication operator.
Definition Aeu.h:502
gpu constexpr friend auto operator+=(Aeu &addition, const Aeu &addendum) noexcept -> Aeu &
Assignment addition operator.
Definition Aeu.h:402
static gpu constexpr auto lcm(const Aeu &first, const Aeu &second) noexcept -> Aeu
Least common multiplier.
Definition Aeu.h:1200
gpu constexpr auto getBit(std::size_t index) const noexcept -> bool
Get bit in number by index staring from the right.
Definition Aeu.h:926
gpu constexpr friend auto operator-(const Aeu &subtraction, const Aeu &subtrahend) noexcept -> Aeu
Subtraction operator.
Definition Aeu.h:416
gpu constexpr auto squareRoot() const noexcept -> Aeu
Get square root.
Definition Aeu.h:1267
gpu constexpr auto getBlock(std::size_t index) const noexcept -> block
Get block in number by index starting from the right.
Definition Aeu.h:986
gpu constexpr friend auto operator*(const Aeu &multiplication, const Aeu &factor) noexcept -> Aeu
Multiplication operator.
Definition Aeu.h:451
gpu constexpr auto operator-() const noexcept -> Aeu
Unary minus operator.
Definition Aeu.h:312
gpu constexpr auto operator++() noexcept -> Aeu &
Prefix increment.
Definition Aeu.h:320
gpu constexpr auto compareTo(const Aeu< otherBitness > &other) const noexcept -> Comparison
Internal comparison operator.
Definition Aeu.h:816
gpu constexpr Aeu() noexcept=default
Default constructor.