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 gpu constexpr friend auto operator==(const Aeu& our, const Aeu& other) noexcept -> bool = default;
765
772 template <std::size_t otherBitness> requires (otherBitness != bitness)
773 gpu constexpr friend auto operator==(const Aeu& our, const Aeu<otherBitness>& other) noexcept -> bool {
774 return our.compareTo(other) == Comparison::equal;
775 };
776 /* --------------------------------------------------------------------------- */
777
778
779 /* ----------------------- @name Comparison operators. ----------------------- */
786 template <typename Unsigned> requires (std::is_unsigned_v<Unsigned> && sizeof(Unsigned) < 8) [[nodiscard]]
787 gpu constexpr auto compareTo(Unsigned other) const noexcept -> Comparison {
788 using enum Comparison;
789
790 if(filledBlocksNumber() > 1) return greater;
791 const auto cmp = static_cast<block>(other);
792
793 if(blocks[0] > cmp)
794 return greater;
795
796 if(blocks[0] < cmp)
797 return less;
798
799 return equal;
800 }
801
808 [[nodiscard]]
809 gpu constexpr auto compareTo(uint64_t other) const noexcept -> Comparison {
810 using enum Comparison;
811 if(filledBlocksNumber() > 2) return greater;
812 const auto base = (static_cast<uint64_t>(blocks[1]) << blockBitLength) | static_cast<uint64_t>(blocks[0]);
813 if(base > other)
814 return greater; else if(base < other) return less; else return equal;
815 }
816
823 template <std::size_t otherBitness = bitness> /*requires (otherBitness != bitness)*/ [[nodiscard]]
824 gpu constexpr auto compareTo(const Aeu<otherBitness>& other) const noexcept -> Comparison {
825 using enum Comparison;
826
827 const auto lowerBlockBorder = (blocksNumber < other.totalBlocksNumber() ? blocksNumber : other.totalBlocksNumber());
828 for(long long i = lowerBlockBorder - 1; i >= 0; --i) {
829 const block thisBlock = blocks[i], otherBlock = other.getBlock(i);
830 if(thisBlock != otherBlock)
831 return (thisBlock > otherBlock ? greater : less);
832 }
833
834 if constexpr (otherBitness != blocksNumber * blockBitLength) {
835 using enum Comparison;
836 if (other.totalBlocksNumber() > blocksNumber) {
837 for (long long i = other.totalBlocksNumber() - 1; i > lowerBlockBorder - 1; --i)
838 if (other.getBlock(i) != 0)
839 return less;
840 } else if (blocksNumber > other.totalBlocksNumber()) {
841 for (long long i = blocksNumber - 1; i > lowerBlockBorder - 1; --i)
842 if (blocks[i] != 0)
843 return greater;
844 }
845 }
846
847 return equal;
848 }
849 /* --------------------------------------------------------------------------- */
850
851
852 /* ------------------------ @name Spaceship operators. ----------------------- */
853#if (defined(__CUDACC__) || __cplusplus < 202002L || defined (PRE_CPP_20)) && !defined DOXYGEN_SKIP
857 gpu constexpr auto operator!=(const Aeu& value) const noexcept -> bool { return !this->operator==(value); }
858 gpu constexpr auto operator<(const Aeu& value) const noexcept -> bool { return this->compareTo(value) == Comparison::less; }
859 gpu constexpr auto operator<=(const Aeu& value) const noexcept -> bool { return !this->operator>(value); }
860 gpu constexpr auto operator>(const Aeu& value) const noexcept -> bool { return this->compareTo(value) == Comparison::greater; }
861 gpu constexpr auto operator>=(const Aeu& value) const noexcept -> bool { return !this->operator<(value); }
862#else
869 gpu constexpr auto operator<=>(const Aeu& other) const noexcept -> std::strong_ordering {
870 switch(this->compareTo(other)) {
871 using enum Comparison;
872 case less:
873 return std::strong_ordering::less;
874 case greater:
875 return std::strong_ordering::greater;
876 case equal:
877 return std::strong_ordering::equal;
878 default:
879 return std::strong_ordering::equivalent;
880 }
881 };
882
889 template <typename Unsigned>
890 gpu constexpr auto operator<=>(const Unsigned& other) const noexcept -> std::strong_ordering {
891 switch(this->compareTo(other)) {
892 using enum Comparison;
893 case less:
894 return std::strong_ordering::less;
895 case greater:
896 return std::strong_ordering::greater;
897 case equal:
898 return std::strong_ordering::equal;
899 default:
900 return std::strong_ordering::equivalent;
901 }
902 };
903#endif
904 /* --------------------------------------------------------------------------- */
905 /* ----------------------------------------------------------------------- */
906
907
908 /* ---------------------- @name Supporting methods. ---------------------- */
915 gpu constexpr auto setBit(std::size_t index, bool bit) noexcept -> void {
916#ifndef AESI_UNSAFE
917 if(index >= bitness) return;
918#endif
919 const std::size_t blockNumber = index / blockBitLength, bitNumber = index % blockBitLength;
920 assert(blockNumber < blocksNumber && bitNumber < blockBitLength);
921 if(bit)
922 blocks[blockNumber] |= (1U << bitNumber);
923 else
924 blocks[blockNumber] &= (~(1U << bitNumber));
925 }
926
933 [[nodiscard]]
934 gpu constexpr auto getBit(std::size_t index) const noexcept -> bool {
935#ifndef AESI_UNSAFE
936 if(index >= bitness) return false;
937#endif
938 const std::size_t blockNumber = index / blockBitLength, bitNumber = index % blockBitLength;
939 assert(blockNumber < blocksNumber && bitNumber < blockBitLength);
940 return blocks[blockNumber] & (1U << bitNumber);
941 }
942
949 gpu constexpr auto setByte(std::size_t index, byte byte) noexcept -> void {
950#ifndef AESI_UNSAFE
951 if(index > blocksNumber * sizeof(block)) return;
952#endif
953 const std::size_t blockNumber = index / sizeof(block), byteInBlock = index % sizeof(block), shift = byteInBlock * bitsInByte;
954 assert(blockNumber < blocksNumber && byteInBlock < sizeof(block));
955 blocks[blockNumber] &= ~(0xffU << shift); blocks[blockNumber] |= static_cast<block>(byte) << shift;
956 }
957
964 [[nodiscard]]
965 gpu constexpr auto getByte(std::size_t index) const noexcept -> byte {
966#ifndef AESI_UNSAFE
967 if(index > blocksNumber * sizeof(block)) return 0;
968#endif
969 const std::size_t blockNumber = index / sizeof(block), byteInBlock = index % sizeof(block), shift = byteInBlock * bitsInByte;
970 assert(blockNumber < blocksNumber && byteInBlock < sizeof(block));
971 return (blocks[blockNumber] & (0xffU << shift)) >> shift;
972 }
973
980 gpu constexpr auto setBlock(std::size_t index, block block) noexcept -> void {
981#ifndef AESI_UNSAFE
982 if(index >= blocksNumber) return;
983#endif
984 blocks[index] = block;
985 }
986
993 [[nodiscard]]
994 gpu constexpr auto getBlock(std::size_t index) const noexcept -> block {
995#ifndef AESI_UNSAFE
996 if(index >= blocksNumber) return block();
997#endif
998 return blocks[index];
999 }
1000
1005 [[nodiscard]]
1006 gpu constexpr auto byteCount() const noexcept -> std::size_t {
1007 std::size_t lastBlock = blocksNumber - 1;
1008 for(; lastBlock > 0 && blocks[lastBlock] == 0; --lastBlock)
1009 ;
1010
1011 for(int8_t byteN = sizeof(block) - 1; byteN >= 0; --byteN) {
1012 if((blocks[lastBlock] & (0xffU << (byteN * bitsInByte))) >> (byteN * bitsInByte))
1013 return lastBlock * sizeof(block) + byteN + 1;
1014 }
1015 return lastBlock * sizeof(block);
1016 }
1017
1022 [[nodiscard]]
1023 gpu constexpr auto bitCount() const noexcept -> std::size_t {
1024 std::size_t lastBlock = blocksNumber - 1;
1025 for(; lastBlock > 0 && blocks[lastBlock] == 0; --lastBlock)
1026 ;
1027
1028 for(int8_t byteN = sizeof(block) - 1; byteN >= 0; --byteN) {
1029 const auto byte = (blocks[lastBlock] & (0xffU << (byteN * bitsInByte))) >> (byteN * bitsInByte);
1030 if(!byte) continue;
1031
1032 for(int8_t bitN = bitsInByte - 1; bitN >= 0; --bitN) {
1033 if((byte & (0x1u << bitN)) >> bitN)
1034 return (lastBlock * sizeof(block) + byteN) * bitsInByte + bitN + 1;
1035 }
1036 return ((lastBlock - 1) * sizeof(block) + byteN) * bitsInByte;
1037 }
1038 return lastBlock * sizeof(block);
1039 }
1040
1045 [[nodiscard]]
1046 gpu constexpr auto isOdd() const noexcept -> bool { return (0x1 & blocks[0]) == 1; }
1047
1052 [[nodiscard]]
1053 gpu constexpr auto isEven() const noexcept -> bool { return (0x1 & blocks[0]) == 0; }
1054
1059 [[nodiscard]]
1060 gpu constexpr auto isZero() const noexcept -> bool { return filledBlocksNumber() == 0; }
1061
1066 [[nodiscard]]
1067 gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t {
1068 for(long long i = blocksNumber - 1; i >= 0; --i)
1069 if(blocks[i]) return i + 1;
1070 return 0;
1071 }
1072
1077 [[nodiscard]]
1078 gpu static constexpr auto getBitness() noexcept -> std::size_t { return bitness; }
1079
1084 [[nodiscard]]
1085 gpu static constexpr auto totalBlocksNumber() noexcept -> std::size_t { return blocksNumber; }
1086
1091 gpu constexpr auto swap(Aeu& other) noexcept -> void {
1092 Aeu t = other; other.operator=(*this); this->operator=(t);
1093 }
1094 /* ----------------------------------------------------------------------- */
1095
1096
1097 /* -------------- @name Public arithmetic and number theory. ------------- */
1106 gpu static constexpr auto divide(const Aeu& number, const Aeu& divisor, Aeu& quotient, Aeu& remainder) noexcept -> void {
1107 const auto ratio = number.compareTo(divisor);
1108
1109 quotient = Aeu {}; remainder = Aeu {};
1110
1111 if(ratio == Comparison::greater) {
1112 const auto bitsUsed = number.filledBlocksNumber() * blockBitLength;
1113 for(long long i = bitsUsed - 1; i >= 0; --i) {
1114 remainder <<= 1u;
1115 remainder.setBit(0, number.getBit(i));
1116
1117 if(remainder >= divisor) {
1118 remainder -= divisor;
1119 quotient.setBit(i, true);
1120 }
1121 }
1122 } else if(ratio == Comparison::less)
1123 remainder = number; else quotient = 1u;
1124 }
1125
1132 [[nodiscard]]
1133 gpu static constexpr auto divide(const Aeu& number, const Aeu& divisor) noexcept -> pair<Aeu, Aeu> {
1134 pair<Aeu, Aeu> results; divide(number, divisor, results.first, results.second); return results;
1135 }
1136
1146 gpu static constexpr auto gcd(const Aeu& first, const Aeu& second, Aeu& bezoutX, Aeu& bezoutY) noexcept -> Aeu {
1147 Aeu gcd, quotient, remainder;
1148
1149 const auto ratio = first.compareTo(second);
1150 if(ratio == Comparison::greater) {
1151 gcd = second;
1152 divide(first, second, quotient, remainder);
1153 } else {
1154 gcd = first;
1155 divide(second, first, quotient, remainder);
1156 }
1157
1158 bezoutX = 0u; bezoutY = 1u;
1159 for(Aeu tX = 1u, tY = 0u; remainder != 0u; ) {
1160 Aeu tGcd = gcd; gcd = remainder;
1161
1162 Aeu t = bezoutX; bezoutX = tX - quotient * bezoutX; tX = t;
1163 t = bezoutY; bezoutY = tY - quotient * bezoutY; tY = t;
1164
1165 divide(tGcd, gcd, quotient, remainder);
1166 }
1167
1168 if(ratio != Comparison::greater)
1169 bezoutX.swap(bezoutY);
1170
1171 return gcd;
1172 }
1173
1181 gpu static constexpr auto gcd(const Aeu& first, const Aeu& second) noexcept -> Aeu {
1182 Aeu gcd, quotient, remainder;
1183
1184 const auto ratio = first.compareTo(second);
1185 if(ratio == Comparison::greater) {
1186 gcd = second;
1187 divide(first, second, quotient, remainder);
1188 } else {
1189 gcd = first;
1190 divide(second, first, quotient, remainder);
1191 }
1192
1193 for(Aeu tX = 1u, tY = 0u; remainder != 0u; ) {
1194 Aeu tGcd = gcd; gcd = remainder;
1195 divide(tGcd, gcd, quotient, remainder);
1196 }
1197
1198 return gcd;
1199 }
1200
1207 [[nodiscard]]
1208 gpu static constexpr auto lcm(const Aeu& first, const Aeu& second) noexcept -> Aeu { return first / gcd(first, second) * second; }
1209
1219 template <std::size_t powerBitness = bitness> [[nodiscard]]
1220 gpu static constexpr auto powm(const Aeu& base, const Aeu<powerBitness>& power, const Aeu& modulo) noexcept -> Aeu {
1221 if(base == 1u)
1222 return base;
1223 if(base == 0u)
1224 return { 1u };
1225
1226 Aeu output = 1u;
1227 auto [_, b] = divide(base, modulo);
1228
1229 for(unsigned iteration = 0; power.filledBlocksNumber() * blockBitLength != iteration; iteration++) {
1230 if(power.getBit(iteration)) {
1231 const auto [quotient, remainder] = divide(output * b, modulo);
1232 output = remainder;
1233 }
1234
1235 const auto [quotient, remainder] = divide(b * b, modulo);
1236 b = remainder;
1237 }
1238
1239 return output;
1240 }
1241
1242 [[nodiscard]]
1243 gpu static constexpr auto powm(const Aeu& base, const Aeu& power, const Aeu& mod) noexcept -> Aeu {
1244 Aeu output = 1u;
1245 auto [_, b] = divide(base, mod);
1246
1247 for(std::size_t iteration = 0; power.filledBlocksNumber() * blockBitLength != iteration; iteration++) {
1248 if(power.getBit(iteration)) {
1249 const auto [quotient, remainder] = divide(output * b, mod);
1250 output = remainder;
1251 }
1252
1253 const auto [quotient, remainder] = divide(b * b, mod);
1254 b = remainder;
1255 }
1256
1257 return output;
1258 }
1259
1266 [[nodiscard]]
1267 gpu static constexpr auto power2(std::size_t power) noexcept -> Aeu { Aeu result {}; result.setBit(power, true); return result; }
1268
1274 [[nodiscard]]
1275 gpu constexpr auto squareRoot() const noexcept -> Aeu {
1276 Aeu x, y = power2((bitCount() + 1) / 2);
1277
1278 do {
1279 x = y;
1280 y = (x + *this / x) >> 1u;
1281 } while (y < x);
1282
1283 return x;
1284 }
1285 /* ----------------------------------------------------------------------- */
1286
1287
1288 /* ----------------- @name Public input-output operators. ---------------- */
1299 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))
1300 gpu constexpr auto getString(Char* const buffer, std::size_t bufferSize, bool showBase = false, bool hexUppercase = false) const noexcept -> std::size_t {
1301 if(bufferSize < 2) return 0;
1302
1303 std::size_t position = 0;
1304
1305 if (showBase && bufferSize > 3) {
1306 if constexpr (base == 2) {
1307 if constexpr (std::is_same_v<Char, char>) {
1308 buffer[0] = '0'; buffer[1] = 'b';
1309 } else {
1310 buffer[0] = L'0'; buffer[1] = L'b';
1311 }
1312 position += 2;
1313 } else if constexpr (base == 8) {
1314 if constexpr (std::is_same_v<Char, char>) {
1315 buffer[0] = '0'; buffer[1] = 'o';
1316 } else {
1317 buffer[0] = L'0'; buffer[1] = L'o';
1318 }
1319 position += 2;
1320 } else if constexpr (base == 16) {
1321 if constexpr (std::is_same_v<Char, char>) {
1322 buffer[0] = '0'; buffer[1] = 'x';
1323 } else {
1324 buffer[0] = L'0'; buffer[1] = L'x';
1325 }
1326 position += 2;
1327 }
1328 }
1329
1330 if(isZero()) {
1331 buffer[position++] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; }}();
1332 return position;
1333 }
1334
1335 if constexpr (base == 16) {
1336 long long iter = blocks.size() - 1;
1337 for (; blocks[iter] == 0 && iter >= 0; --iter)
1338 ;
1339
1340 if constexpr (std::is_same_v<Char, char>) {
1341 position += snprintf(buffer + position, bufferSize - position, (hexUppercase ? "%X" : "%x"), blocks[iter--]);
1342 for (; iter >= 0; --iter)
1343 position += snprintf(buffer + position, bufferSize - position, (hexUppercase ? "%08X" : "%08x"), blocks[iter]);
1344 } else {
1345 position += swprintf(buffer + position, bufferSize - position, (hexUppercase ? L"%X" : L"%x"), blocks[iter--]);
1346 for (; iter >= 0; --iter)
1347 position += swprintf(buffer + position, bufferSize - position, (hexUppercase ? L"%08X" : L"%08x"), blocks[iter]);
1348 }
1349 } else {
1350 const auto startPosition = position;
1351
1352 Aeu copy = *this;
1353 while (!copy.isZero() && position < bufferSize) {
1354 auto [quotient, remainder] = divide(copy, base);
1355 if constexpr (std::is_same_v<Char, char>) {
1356 buffer[position++] = '0' + remainder.template integralCast<byte>();
1357 } else {
1358 buffer[position++] = L'0' + remainder.template integralCast<byte>();
1359 }
1360 copy = quotient;
1361 }
1362 const auto digitsTotal = position - startPosition;
1363 for (std::size_t i = 0; i * 2 < digitsTotal; ++i) {
1364 Char t = buffer[startPosition + i];
1365 buffer[startPosition + i] = buffer[startPosition + digitsTotal - 1 - i];
1366 buffer[startPosition + digitsTotal - 1 - i] = t;
1367 }
1368 }
1369 buffer[position++] = Char {};
1370 return position;
1371 }
1372
1384 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1385 friend constexpr auto operator<<(std::basic_ostream<Char>& os, const Aeu& number) -> std::basic_ostream<Char>& {
1386 auto flags = os.flags();
1387
1388 const auto base = [] (long baseField, std::basic_ostream<Char>& ss, bool showbase) {
1389 auto tBase = (baseField == std::ios::hex ? 16u : (baseField == std::ios::oct ? 8u : 10u));
1390 if(showbase && tBase != 10)
1391 ss << [&tBase] {
1392 if constexpr (std::is_same_v<Char, char>) {
1393 return tBase == 8 ? "0o" : "0x";
1394 } else {
1395 return tBase == 8 ? L"0o" : L"0x";
1396 }
1397 } () << std::noshowbase ;
1398 return tBase;
1399 } (flags & std::ios::basefield, os, flags & std::ios::showbase);
1400
1401 if(number.isZero())
1402 return os << '0';
1403
1404 if(base == 16) {
1405 long long iter = number.blocks.size() - 1;
1406 for(; number.blocks[iter] == 0 && iter >= 0; --iter)
1407 ;
1408
1409 os << number.blocks[iter--];
1410 for (; iter >= 0; --iter) {
1411 os.fill([] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ());
1412 os.width(8); os << std::right << number.blocks[iter];
1413 }
1414 } else {
1415 /* Well, here we use a pre-calculated magic number to ratio the length of numbers in decimal or octal notation according to bitness.
1416 * * It is 2.95-98 for octal and 3.2 for decimal. */
1417 constexpr auto bufferSize = static_cast<std::size_t>(static_cast<double>(bitness) / 2.95);
1418 Char buffer [bufferSize] {}; std::size_t filled = 0;
1419
1420 Aeu copy = number;
1421 while(!copy.isZero() && filled < bufferSize) {
1422 const auto [quotient, remainder] = divide(copy, base);
1423 buffer[filled++] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } () + remainder.template integralCast<byte>();
1424 copy = quotient;
1425 }
1426
1427 for(; filled > 0; --filled)
1428 os << buffer[filled - 1];
1429 }
1430
1431 return os;
1432 }
1433
1434
1443 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1444 constexpr auto readBinary(std::basic_istream<Char>& is, bool bigEndian = true) -> void {
1445 blocks = {};
1446 if(bigEndian) {
1447 for(auto it = blocks.rbegin(); it != blocks.rend(); ++it)
1448 if(!is.read(reinterpret_cast<char*>(&*it), sizeof(block))) break;
1449 } else {
1450 for(auto& tBlock: blocks)
1451 if(!is.read(reinterpret_cast<char*>(&tBlock), sizeof(block))) break;
1452 }
1453 }
1454
1455
1462 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1463 constexpr auto writeBinary(std::basic_ostream<Char>& os, bool bigEndian = true) const noexcept -> void {
1464 if(bigEndian) {
1465 for(auto it = blocks.rbegin(); it != blocks.rend(); ++it)
1466 if(!os.write(reinterpret_cast<const char*>(&*it), sizeof(block))) break;
1467 } else {
1468 for(auto& block: blocks)
1469 if(!os.write(reinterpret_cast<const char*>(&block), sizeof(block))) break;
1470 }
1471 }
1472 /* ----------------------------------------------------------------------- */
1473
1474
1475 /* -------------------- @name Public casting operators. ------------------ */
1481 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
1482 gpu constexpr auto integralCast() const noexcept -> Integral {
1483 const uint64_t value = (static_cast<uint64_t>(blocks[1]) << blockBitLength) | static_cast<uint64_t>(blocks[0]);
1484 return static_cast<Integral>(value);
1485 }
1486
1495 template <std::size_t newBitness> requires (newBitness != bitness) [[nodiscard]]
1496 gpu constexpr auto precisionCast() const noexcept -> Aeu<newBitness> {
1497 Aeu<newBitness> result {};
1498
1499 const std::size_t blockBoarder = (newBitness > bitness ? Aeu<bitness>::totalBlocksNumber() : Aeu<newBitness>::totalBlocksNumber());
1500 for(std::size_t blockIdx = 0; blockIdx < blockBoarder; ++blockIdx)
1501 result.setBlock(blockIdx, getBlock(blockIdx));
1502
1503 return result;
1504 }
1505 /* ----------------------------------------------------------------------- */
1506
1507
1508#if defined __CUDACC__
1509 /* ------------------- @name Atomic-like CUDA operators. ----------------- */
1516 __device__ constexpr auto tryAtomicSet(const Aeu& value) noexcept -> void {
1517 for(std::size_t i = 0; i < blocksNumber; ++i)
1518 atomicExch(&blocks[i], value.blocks[i]);
1519 }
1520
1527 __device__ constexpr auto tryAtomicExchange(const Aeu& value) noexcept -> void {
1528 for(std::size_t i = 0; i < blocksNumber; ++i)
1529 atomicExch(&value.blocks[i], atomicExch(&blocks[i], value.blocks[i]));
1530 }
1531 /* ----------------------------------------------------------------------- */
1532#endif
1533};
1534
1535/* -------------------------------------------- @name Type-definitions ------------------------------------------- */
1540
1545
1550
1555
1560
1565
1570
1575
1580
1585
1590/* ---------------------------------------------------------------------------------------------------------------- */
1591
1592/* ------------------------------------------ @name Integral conversions ----------------------------------------- */
1599template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1600gpu constexpr auto operator+(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) + value; }
1601
1608template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1609gpu constexpr auto operator-(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) - value; }
1610
1617template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1618gpu constexpr auto operator*(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) * value; }
1619
1626template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1627gpu constexpr auto operator/(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) / value; }
1628
1635template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1636gpu constexpr auto operator%(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) % value; }
1637
1644template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1645gpu constexpr auto operator^(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) ^ value; }
1646
1653template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1654gpu constexpr auto operator&(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) & value; }
1655
1662template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1663gpu constexpr auto operator|(Integral number, const Aeu<bitness>& value) noexcept { return Aeu<bitness>(number) | value; }
1664/* ---------------------------------------------------------------------------------------------------------------- */
1665
1666#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:1146
gpu constexpr auto operator<=>(const Aeu &other) const noexcept -> std::strong_ordering
Three-way comparison operator.
Definition Aeu.h:869
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:1023
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:787
gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t
Get number of non-empty blocks inside object starting from the right.
Definition Aeu.h:1067
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:1300
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:1267
static gpu constexpr auto gcd(const Aeu &first, const Aeu &second) noexcept -> Aeu
Greatest common divisor.
Definition Aeu.h:1181
gpu constexpr auto isEven() const noexcept -> bool
Check whether number is even.
Definition Aeu.h:1053
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:949
gpu constexpr friend auto operator+(const Aeu &addition, const Aeu &addendum) noexcept -> Aeu
Addition operator.
Definition Aeu.h:377
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:1006
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:980
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:965
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:1220
gpu constexpr auto integralCast() const noexcept -> Integral
Integral type cast operator for built-in types.
Definition Aeu.h:1482
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:1046
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:1463
static gpu constexpr auto divide(const Aeu &number, const Aeu &divisor) noexcept -> pair< Aeu, Aeu >
Integer division. Returns results by value.
Definition Aeu.h:1133
gpu constexpr auto swap(Aeu &other) noexcept -> void
Make swap between two objects.
Definition Aeu.h:1091
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:1106
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:1078
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:915
gpu constexpr auto precisionCast() const noexcept -> Aeu< newBitness >
Precision cast operator.
Definition Aeu.h:1496
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:1085
gpu constexpr auto isZero() const noexcept -> bool
Check whether number is zero.
Definition Aeu.h:1060
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:890
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:1444
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:809
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:1208
gpu constexpr auto getBit(std::size_t index) const noexcept -> bool
Get bit in number by index staring from the right.
Definition Aeu.h:934
gpu constexpr friend auto operator-(const Aeu &subtraction, const Aeu &subtrahend) noexcept -> Aeu
Subtraction operator.
Definition Aeu.h:416
gpu constexpr friend auto operator==(const Aeu &our, const Aeu &other) noexcept -> bool=default
Equality check operator for numbers of the same precision.
gpu constexpr auto squareRoot() const noexcept -> Aeu
Get square root.
Definition Aeu.h:1275
gpu constexpr auto getBlock(std::size_t index) const noexcept -> block
Get block in number by index starting from the right.
Definition Aeu.h:994
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:824
gpu constexpr Aeu() noexcept=default
Default constructor.