Aesi Multiprecision
C++ class library of long integer arithmetic for GPU parallelization
Loading...
Searching...
No Matches
Aesi.h
Go to the documentation of this file.
1
31#ifndef AESI_MULTIPRECISION
32#define AESI_MULTIPRECISION
33
35#include "Aeu.h"
37
38namespace {
39 enum class Sign { Zero = 0, Positive = 1, Negative = -1 };
40
41 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
42 Sign traverseDashes(const Char* ptr, std::size_t);
43
44 template <>
45 Sign traverseDashes(const char* ptr, std::size_t size) {
46 std::byte positive { 1 };
47 for(std::size_t i = 0; i < size; ++i)
48 if(ptr[i] == '-') positive ^= std::byte {1};
49 return positive == std::byte {1} ? Sign::Positive : Sign::Negative;
50 }
51
52 template <>
53 Sign traverseDashes(const wchar_t* ptr, std::size_t size) {
54 std::byte positive { 1 };
55 for(std::size_t i = 0; i < size; ++i)
56 if(ptr[i] == L'-') positive ^= std::byte {1};
57 return positive == std::byte {1} ? Sign::Positive : Sign::Negative;
58 }
59}
66template <std::size_t bitness = 512> requires (bitness % blockBitLength == 0)
67class Aesi final {
68 /* -------------------------- @name Class members. ----------------------- */
69 Sign sign;
70
71 using Base = Aeu<bitness>;
72 Base base;
73 /* ----------------------------------------------------------------------- */
74
75 gpu constexpr Aesi(Sign withSign, Base withBase): sign { withSign }, base { withBase } {}
76
77public:
78 /* --------------------- @name Different constructors. ------------------- */
82 gpu constexpr Aesi() noexcept = default;
83
87 gpu constexpr ~Aesi() noexcept = default;
88
93 gpu constexpr Aesi(const Aesi& copy) noexcept = default;
94
99 template <typename Integral> requires (std::is_integral_v<Integral>)
100 gpu constexpr Aesi(Integral value) noexcept {
101 using enum Sign;
102 if(value < 0) {
103 value *= -1;
104 base = Base(static_cast<unsigned long long>(value));
105 sign = Negative;
106 } else if(value > 0) {
107 base = Base(static_cast<unsigned long long>(value));
108 sign = Positive;
109 } else
110 sign = Zero;
111 }
112
120 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
121 gpu constexpr Aesi(const Char* ptr, std::size_t size) noexcept : base(ptr, size) {
122 if(!base.isZero())
123 sign = traverseDashes(ptr, size);
124 else sign = Sign::Zero;
125 }
126
131 template <typename Char, std::size_t arrayLength> requires (arrayLength > 1 && (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>))
132 gpu constexpr Aesi(const Char (&literal)[arrayLength]) noexcept : Aesi(literal, arrayLength) {}
133
138 template <typename String, typename Char = typename String::value_type> requires (std::is_same_v<std::basic_string<Char>,
139 std::decay_t<String>> || std::is_same_v<std::basic_string_view<Char>, std::decay_t<String>>)
140 gpu constexpr Aesi(String&& stringView) noexcept : Aesi(stringView.data(), stringView.size()) {}
141
142 template <typename String, typename Char = typename String::value_type> requires (std::is_same_v<std::basic_string<Char>,
143 std::decay_t<String>> || std::is_same_v<std::basic_string_view<Char>, std::decay_t<String>>)
144 gpu constexpr Aesi(const String& stringView) noexcept : Aesi(stringView.data(), stringView.size()) {}
145
150 explicit gpu constexpr Aesi(const Aeu<bitness>& value) : sign(Sign::Positive), base(value) {}
151
152#ifdef AESI_CRYPTOPP_INTEGRATION
157 constexpr Aesi(const CryptoPP::Integer& number) {
158 using enum Sign;
159 if(number.IsZero())
160 sign = Zero;
161 else {
162 base = number;
163 if(number.IsNegative())
164 sign = Negative;
165 else sign = Positive;
166 }
167 }
168#endif
169
170#ifdef AESI_GMP_INTEGRATION
175 constexpr Aesi(const mpz_class& number) {
176 using enum Sign;
177 if(number == 0)
178 sign = Zero;
179 else {
180 base = number;
181 if(number < 0)
182 sign = Negative;
183 else sign = Positive;
184 }
185 }
186#endif
187
192 template <typename Integral> requires (std::is_signed_v<Integral>)
193 gpu constexpr Aesi& operator=(Integral value) noexcept {
194 using enum Sign;
195 if(value != 0) {
196 if(value < 0) {
197 sign = Negative;
198 value *= -1;
199 } else sign = Positive;
200 base = static_cast<unsigned long long>(value);
201 } else sign = Zero;
202 return *this;
203 }
204
209 gpu constexpr Aesi& operator=(const Aesi& other) noexcept = default;
210 /* ----------------------------------------------------------------------- */
211
212
213 /* --------------------- @name Arithmetic operators. --------------------- */
214 /* ------------------------- @name Unary operators. -------------------------- */
220 gpu constexpr auto operator+() const noexcept -> Aesi { return *this; }
221
226 [[nodiscard]]
227 gpu constexpr auto operator-() const noexcept -> Aesi { Aesi copy = *this; copy.inverse(); return copy; }
228
233 gpu constexpr auto operator++() noexcept -> Aesi& {
234 using enum Sign;
235 if(sign == Negative) {
236 --base; if(base.isZero()) sign = Zero;
237 } else if(sign == Positive) {
238 ++base;
239 } else { base = 1u; sign = Positive; }
240 return *this;
241 }
242
247 gpu constexpr auto operator++(int) & noexcept -> Aesi { Aesi old = *this; operator++(); return old; }
248
253 gpu constexpr auto operator--() noexcept -> Aesi& {
254 using enum Sign;
255 if(sign == Negative) {
256 ++base;
257 } else if(sign == Positive) {
258 --base; if(base.isZero()) sign = Zero;
259 } else { base = 1u; sign = Negative; }
260 return *this;
261 }
262
267 gpu constexpr auto operator--(int) & noexcept -> Aesi { Aesi old = *this; operator--(); return old; }
268 /* --------------------------------------------------------------------------- */
269
270 /* ------------------------ @name Addition operators. ------------------------ */
277 [[nodiscard]]
278 gpu constexpr friend auto operator+(const Aesi& addition, const Aesi& addendum) noexcept -> Aesi {
279 Aesi result = addition; result += addendum; return result;
280 }
281
288 gpu constexpr friend auto operator+=(Aesi& addition, const Aesi& addendum) noexcept -> Aesi& {
289 using enum Sign;
290 Sign& lSign = addition.sign; const Sign& rSign = addendum.sign;
291 Base& lBase = addition.base; const Base& rBase = addendum.base;
292
293 if(rSign == Zero)
294 return addition;
295 else if(lSign == Zero)
296 return addition = addendum;
297 else if(lSign == rSign) {
298 lBase += rBase;
299 return addition;
300 }
301
302 if(lSign == Positive) {
303 switch(lBase.compareTo(rBase)) {
304 using enum Comparison;
305 case greater: {
306 lBase -= rBase;
307 return addition;
308 }
309 case less: {
310 lBase = rBase - lBase;
311 lSign = Negative;
312 return addition;
313 }
314 default: {
315 lSign = Zero;
316 return addition;
317 }
318 }
319 } else {
320 switch(const auto ratio = lBase.compareTo(rBase)) {
321 using enum Comparison;
322 case greater: {
323 lBase -= rBase;
324 return addition;
325 }
326 case less: {
327 lBase = rBase - lBase;
328 lSign = Positive;
329 return addition;
330 }
331 default: {
332 lSign = Zero;
333 return addition;
334 }
335 }
336 }
337 }
338 /* --------------------------------------------------------------------------- */
339
340 /* ----------------------- @name Subtraction operators. ---------------------- */
347 [[nodiscard]]
348 gpu constexpr friend auto operator-(const Aesi& subtraction, const Aesi& subtrahend) noexcept -> Aesi {
349 Aesi result = subtraction; result -= subtrahend; return result;
350 }
351
358 gpu constexpr friend auto operator-=(Aesi& subtraction, const Aesi& subtrahend) noexcept -> Aesi& {
359 using enum Sign;
360 Sign& lSign = subtraction.sign; const Sign& rSign = subtrahend.sign;
361 Base& lBase = subtraction.base; const Base& rBase = subtrahend.base;
362
363 if(rSign == Zero)
364 return subtraction;
365 if(lSign == Zero) {
366 subtraction = subtrahend;
367 subtraction.inverse();
368 return subtraction;
369 }
370
371 if(lSign == Positive) {
372 if(rSign == Positive) {
373 switch(lBase.compareTo(rBase)) {
374 using enum Comparison;
375 case greater: {
376 lBase -= rBase;
377 return subtraction;
378 }
379 case less: {
380 lBase = rBase - lBase;
381 lSign = Negative;
382 return subtraction;
383 }
384 default: {
385 lSign = Zero;
386 return subtraction;
387 }
388 }
389 } else {
390 lBase += rBase;
391 return subtraction;
392 }
393 } else {
394 if(rSign == Negative) {
395 switch(lBase.compareTo(rBase)) {
396 using enum Comparison;
397 case greater: {
398 lBase -= rBase;
399 return subtraction;
400 }
401 case less: {
402 lBase = rBase - lBase;
403 lSign = Positive;
404 return subtraction;
405 }
406 default: {
407 lSign = Zero;
408 return subtraction;
409 }
410 }
411 } else {
412 lBase += rBase;
413 return subtraction;
414 }
415 }
416 }
417 /* --------------------------------------------------------------------------- */
418
419 /* --------------------- @name Multiplication operators. --------------------- */
426 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
427 gpu constexpr friend auto operator*(const Aesi& multiplication, Integral factor) noexcept -> Aesi {
428 Aesi result = multiplication; result *= factor; return result;
429 }
430
437 [[nodiscard]]
438 gpu constexpr friend auto operator*(const Aesi& multiplication, const Aesi& factor) noexcept -> Aesi {
439 Aesi result = multiplication; result *= factor; return result;
440 }
441
448 template <typename Integral> requires (std::is_integral_v<Integral>)
449 gpu constexpr friend auto operator*=(Aesi& multiplication, Integral factor) noexcept -> Aesi& {
450 using enum Sign;
451 if(factor == 0) {
452 multiplication.sign = Zero;
453 } else {
454 if(factor < 0) {
455 multiplication.inverse();
456 factor *= -1;
457 }
458 multiplication.base *= static_cast<unsigned long long>(factor);
459 }
460 return multiplication;
461 }
462
469 gpu constexpr friend auto operator*=(Aesi& multiplication, const Aesi& factor) noexcept -> Aesi& {
470 using enum Sign;
471 if(factor.isZero()) {
472 multiplication.sign = Zero;
473 } else {
474 if(factor.isNegative())
475 multiplication.inverse();
476 multiplication.base *= factor.base;
477 }
478 return multiplication;
479 }
480 /* --------------------------------------------------------------------------- */
481
482 /* ------------------------ @name Division operators. ------------------------ */
490 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
491 gpu constexpr friend auto operator/(const Aesi& division, Integral divisor) noexcept -> Aesi {
492 Aesi result = division; result /= divisor; return result;
493 }
494
502 [[nodiscard]]
503 gpu constexpr friend auto operator/(const Aesi& division, const Aesi& divisor) noexcept -> Aesi {
504 Aesi result = division; result /= divisor; return result;
505 }
506
514 template <typename Integral> requires (std::is_integral_v<Integral>)
515 gpu constexpr friend auto operator/=(Aesi& division, Integral divisor) noexcept -> Aesi& {
516 using enum Sign;
517 if(divisor == 0) {
518 division.sign = Zero;
519 } else {
520 if(divisor < 0) {
521 division.inverse();
522 divisor *= -1;
523 }
524 division.base /= static_cast<unsigned long long>(divisor);
525 if(division.base.isZero()) division.sign = Zero;
526 }
527 return division;
528 }
529
537 gpu constexpr friend auto operator/=(Aesi& division, const Aesi& divisor) noexcept -> Aesi& {
538 using enum Sign;
539 if(divisor.isZero()) {
540 division.sign = Zero;
541 } else {
542 if(divisor.isNegative())
543 division.inverse();
544 division.base /= divisor.base;
545 if(division.base.isZero()) division.sign = Zero;
546 }
547 return division;
548 }
549 /* --------------------------------------------------------------------------- */
550
551 /* ------------------------- @name Modulo operators. ------------------------- */
559 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
560 gpu constexpr friend auto operator%(const Aesi& modulation, Integral modulo) noexcept -> Aesi {
561 Aesi result = modulation; result %= modulo; return result;
562 }
563
572 [[nodiscard]]
573 gpu constexpr friend auto operator%(const Aesi& modulation, const Aesi& modulo) noexcept -> Aesi {
574 Aesi result = modulation; result %= modulo; return result;
575 }
576
584 template <typename Integral> requires (std::is_integral_v<Integral>)
585 gpu constexpr friend auto operator%=(Aesi& modulation, Integral modulo) noexcept -> Aesi& {
586 using enum Sign;
587 if(modulo == 0) {
588 modulation.sign = Zero;
589 } else {
590 if(modulo < 0) {
591 modulation.inverse();
592 modulo *= -1;
593 }
594 modulation.base %= static_cast<unsigned long long>(modulo);
595 }
596 return modulation;
597 }
598
607 gpu constexpr friend auto operator%=(Aesi& modulation, const Aesi& modulo) noexcept -> Aesi& {
608 if(modulo.isZero())
609 return modulation;
610
611 if(modulo.isNegative())
612 modulation.inverse();
613 modulation.base %= modulo.base;
614 if(modulation.base.isZero())
615 modulation.sign = Sign::Zero;
616
617 return modulation;
618 }
619 /* --------------------------------------------------------------------------- */
620 /* ----------------------------------------------------------------------- */
621
622 /* --------------------- @name Comparison operators. --------------------- */
623 /* ------------------------ @name Equality operators. ------------------------ */
630 template <typename Integral> requires (std::is_integral_v<Integral>)
631 gpu constexpr friend auto operator==(const Aesi& our, Integral integral) noexcept -> bool {
632 return our.compareTo(integral) == Comparison::equal;
633 }
634
641 template <std::size_t otherBitness>
642 gpu constexpr friend auto operator==(const Aesi& our, const Aesi<otherBitness>& other) noexcept -> bool {
643 if constexpr (bitness == otherBitness) {
644 return our.compareTo(other) == Comparison::equal;
645 } else {
646 return our.precisionCast<otherBitness>() == other;
647 }
648 }
649 /* --------------------------------------------------------------------------- */
650
651
652 /* ----------------------- @name Comparison operators. ----------------------- */
658 template <typename Integral> requires (std::is_integral_v<Integral>)
659 gpu constexpr auto compareTo(Integral integral) const noexcept -> Comparison {
660 using enum Sign; using enum Comparison;
661 if(integral == 0) {
662 switch(sign) {
663 case Positive:
664 return greater;
665 case Negative:
666 return less;
667 default:
668 return equal;
669 }
670 } else if(integral < 0) {
671 if(sign == Negative)
672 switch(base.compareTo(static_cast<unsigned long long>(integral * -1))) {
673 using enum Comparison;
674 case greater:
675 return less;
676 case less:
677 return greater;
678 default:
679 return equal;
680 }
681 else return greater;
682 } else {
683 if(sign == Positive)
684 return base.compareTo(static_cast<unsigned long long>(integral));
685 return less;
686 }
687 }
688
694 template <std::size_t otherBitness = bitness> [[nodiscard]]
695 gpu constexpr auto compareTo(const Aesi<otherBitness>& value) const noexcept -> Comparison {
696 return precisionCast<otherBitness>().compareTo(value);
697 }
698
704 [[nodiscard]]
705 gpu constexpr auto compareTo(const Aesi& value) const noexcept -> Comparison {
706 using enum Sign; using enum Comparison;
707 if(value.isZero()) {
708 switch(sign) {
709 case Positive:
710 return greater;
711 case Negative:
712 return less;
713 default:
714 return equal;
715 }
716 }
717
718 if(value.isNegative()) {
719 if(sign == Negative)
720 switch(base.compareTo(value.base)) {
721 case greater:
722 return less;
723 case less:
724 return greater;
725 default:
726 return equal;
727 }
728 return greater;
729 }
730
731 if(sign == Positive)
732 return base.compareTo(value.base);
733 return less;
734 }
735 /* --------------------------------------------------------------------------- */
736
737 /* ------------------------ @name Spaceship operators. ----------------------- */
738#if (defined(__CUDACC__) || __cplusplus < 202002L || defined (PRE_CPP_20)) && !defined DOXYGEN_SKIP
742 gpu constexpr auto operator!=(const Aeu& value) const noexcept -> bool {
743 return !this->operator==(value);
744 }
745 gpu constexpr auto operator<(const Aeu& value) const noexcept -> bool {
746 return this->compareTo(value) == Comparison::less;
747 }
748 gpu constexpr auto operator<=(const Aeu& value) const noexcept -> bool {
749 return !this->operator>(value);
750 }
751 gpu constexpr auto operator>(const Aeu& value) const noexcept -> bool {
752 return this->compareTo(value) == Comparison::greater;
753 }
754 gpu constexpr auto operator>=(const Aeu& value) const noexcept -> bool {
755 return !this->operator<(value);
756 }
757#else
764 gpu constexpr auto operator<=>(const Aesi& other) const noexcept -> std::strong_ordering {
765 switch(this->compareTo(other)) {
766 using enum Comparison;
767 case less:
768 return std::strong_ordering::less;
769 case greater:
770 return std::strong_ordering::greater;
771 case equal:
772 return std::strong_ordering::equal;
773 default:
774 return std::strong_ordering::equivalent;
775 }
776 }
777
784 template <typename Object>
785 gpu constexpr auto operator<=>(const Object& other) const noexcept -> std::strong_ordering {
786 switch(this->compareTo(other)) {
787 using enum Comparison;
788 case less:
789 return std::strong_ordering::less;
790 case greater:
791 return std::strong_ordering::greater;
792 case equal:
793 return std::strong_ordering::equal;
794 default:
795 return std::strong_ordering::equivalent;
796 }
797 };
798#endif
799 /* --------------------------------------------------------------------------- */
800 /* ----------------------------------------------------------------------- */
801
802 /* ---------------------- @name Supporting methods. ---------------------- */
809 gpu constexpr auto setBit(std::size_t index, bool bit) noexcept -> void { return base.setBit(index, bit); }
810
817 [[nodiscard]]
818 gpu constexpr auto getBit(std::size_t index) const noexcept -> bool { return base.getBit(index); }
819
826 gpu constexpr auto setByte(std::size_t index, byte byte) noexcept -> void { return base.setByte(index, byte); }
827
834 [[nodiscard]]
835 gpu constexpr auto getByte(std::size_t index) const noexcept -> byte { return base.getByte(index); }
836
843 gpu constexpr auto setBlock(std::size_t index, block block) noexcept -> void { return base.setBlock(index, block); }
844
851 [[nodiscard]]
852 gpu constexpr auto getBlock(std::size_t index) const noexcept -> block { return base.getBlock(index); }
853
858 [[nodiscard]]
859 gpu constexpr auto byteCount() const noexcept -> std::size_t { return base.byteCount(); }
860
865 [[nodiscard]]
866 gpu constexpr auto bitCount() const noexcept -> std::size_t { return base.bitCount(); }
867
872 [[nodiscard]]
873 gpu constexpr auto isOdd() const noexcept -> bool { return base.isOdd(); }
874
879 [[nodiscard]]
880 gpu constexpr auto isEven() const noexcept -> bool { return base.isEven(); }
881
886 [[nodiscard]]
887 gpu constexpr auto isZero() const noexcept -> bool { return sign == Sign::Zero; }
888
893 [[nodiscard]]
894 gpu constexpr auto isPositive() const noexcept -> bool { return sign == Sign::Positive; }
895
900 [[nodiscard]]
901 gpu constexpr auto isNegative() const noexcept -> bool { return sign == Sign::Negative; }
902
907 [[nodiscard]]
908 gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t { return base.filledBlocksNumber(); }
909
914 [[nodiscard]]
915 gpu static constexpr auto getBitness() noexcept -> std::size_t { return bitness; }
916
921 [[nodiscard]]
922 gpu static constexpr auto totalBlocksNumber() noexcept -> std::size_t { return Aeu<bitness>::totalBlocksNumber(); }
923
928 gpu constexpr auto swap(Aesi& other) noexcept -> void {
929 Sign tSign = sign; sign = other.sign; other.sign = tSign;
930 base.swap(other.base);
931 }
932
937 gpu constexpr auto inverse() noexcept -> void {
938 using enum Sign;
939 sign = (sign == Zero ? Zero : (sign == Negative ? Positive : Negative));
940 }
941 /* ----------------------------------------------------------------------- */
942
943 /* -------------- @name Public arithmetic and number theory. ------------- */
952 gpu static constexpr auto divide(const Aesi& number, const Aesi& divisor, Aesi& quotient, Aesi& remainder) noexcept -> void {
953 using enum Sign;
954 if(number.sign == Zero || divisor.sign == Zero) {
955 quotient.sign = Zero;
956 remainder.sign = Zero;
957 return;
958 }
959
960 Base::divide(number.base, divisor.base, quotient.base, remainder.base);
961 if(number.sign == Positive) {
962 if(divisor.sign == Positive) {
963 quotient.sign = Positive;
964 remainder.sign = Positive;
965 } else {
966 quotient.sign = Negative;
967 remainder.sign = Positive;
968 }
969 } else {
970 if(divisor.sign == Positive) {
971 quotient.sign = Negative;
972 remainder.sign = Negative;
973 } else {
974 quotient.sign = Positive;
975 remainder.sign = Negative;
976 }
977 }
978
979 if(quotient.base.isZero())
980 quotient.sign = Zero;
981 if(remainder.base.isZero())
982 remainder.sign = Zero;
983 }
984
990 [[nodiscard]]
991 gpu constexpr auto squareRoot() const noexcept -> Aesi {
992 using enum Sign;
993 if(sign == Positive)
994 return Aesi { Positive, base.squareRoot() };
995 Aesi result; result.sign = Zero; return result;
996 }
997
1002 [[nodiscard]]
1003 gpu static constexpr auto power2(std::size_t power) noexcept -> Aesi {
1004 using enum Sign;
1005 Aesi result { Positive, Aeu<bitness>::power2(power) };
1006 if(result.base.isZero())
1007 result.sign = Zero;
1008 return result;
1009 }
1010 /* ----------------------------------------------------------------------- */
1011
1016 template <typename Integral> requires (std::is_integral_v<Integral>) [[nodiscard]]
1017 gpu constexpr auto integralCast() const noexcept -> Integral {
1018 using enum Sign;
1019 if(sign == Zero)
1020 return Integral(0);
1021
1022 if constexpr (std::is_signed_v<Integral>) {
1023 if(sign == Negative)
1024 return base.template integralCast<Integral>() * -1;
1025 }
1026
1027 return base.template integralCast<Integral>();
1028 }
1029
1034 template <std::size_t newBitness> requires (newBitness != bitness) [[nodiscard]]
1035 gpu constexpr auto precisionCast() const noexcept -> Aesi<newBitness> {
1036 using enum Sign;
1037 if(sign != Zero) {
1038 Aesi<newBitness> result = 1;
1039
1040 const std::size_t blockBoarder = (newBitness > bitness ? totalBlocksNumber() : Aesi<newBitness>::totalBlocksNumber());
1041 for(std::size_t blockIdx = 0; blockIdx < blockBoarder; ++blockIdx)
1042 result.setBlock(blockIdx, getBlock(blockIdx));
1043
1044 if(sign == Negative)
1045 result.inverse();
1046
1047 return result;
1048 }
1049
1050 return Aesi<newBitness> {};
1051 }
1052
1057 gpu constexpr auto unsignedCast() const noexcept -> Aeu<bitness> { return base; }
1058
1059 /* ----------------- @name Public input-output operators. ---------------- */
1070 template <byte notation, typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t> && (notation == 2 || notation == 8 || notation == 10 || notation == 16))
1071 gpu constexpr auto getString(Char* buffer, std::size_t bufferSize, bool showBase = false, bool hexUppercase = false) const noexcept -> std::size_t {
1072 using enum Sign;
1073
1074 if(sign != Zero) {
1075 if(sign == Negative && bufferSize > 0) {
1076 *buffer++ = [] { if constexpr (std::is_same_v<Char, char>) { return '-'; } else { return L'-'; } } ();
1077 --bufferSize;
1078 }
1079 return base.template getString<notation, Char>(buffer, bufferSize, showBase, hexUppercase);
1080 }
1081
1082 if(showBase) {
1083 switch(notation) {
1084 case 2: {
1085 if(bufferSize < 3) return 0;
1086 buffer[0] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ();
1087 buffer[1] = [] { if constexpr (std::is_same_v<Char, char>) { return 'b'; } else { return L'b'; } } ();
1088 buffer[2] = buffer[0];
1089 return 3;
1090 }
1091 case 8: {
1092 if(bufferSize < 3) return 0;
1093 buffer[0] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ();
1094 buffer[1] = [] { if constexpr (std::is_same_v<Char, char>) { return 'o'; } else { return L'o'; } } ();
1095 buffer[2] = buffer[0];
1096 return 3;
1097 }
1098 case 16: {
1099 if(bufferSize < 3) return 0;
1100 buffer[0] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ();
1101 buffer[1] = [] { if constexpr (std::is_same_v<Char, char>) { return 'x'; } else { return L'x'; } } ();
1102 buffer[2] = buffer[0];
1103 return 3;
1104 }
1105 default: {
1106 if(bufferSize < 1) return 0;
1107 buffer[0] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ();
1108 return 1;
1109 }
1110 }
1111 }
1112
1113 buffer[0] = [] { if constexpr (std::is_same_v<Char, char>) { return '0'; } else { return L'0'; } } ();
1114 return 1;
1115 }
1116
1128 template <typename Char> requires (std::is_same_v<Char, char> || std::is_same_v<Char, wchar_t>)
1129 friend constexpr auto operator<<(std::basic_ostream<Char>& os, const Aesi& number) -> std::basic_ostream<Char>& {
1130 using enum Sign;
1131 if(number.sign != Zero) {
1132 if(number.sign == Negative)
1133 os << [] { if constexpr (std::is_same_v<Char, char>) { return '-'; } else { return L'-'; } } ();
1134 return os << number.base;
1135 }
1136 return os << '0';
1137 }
1138 /* ----------------------------------------------------------------------- */
1139
1140#if defined __CUDACC__ || defined DOXYGEN_SKIP
1147 __device__ constexpr auto tryAtomicSet(const Aesi& value) noexcept -> void {
1148 base.tryAtomicSet(value.base);
1149 sign = value.sign; /* TODO: Make enum substitution using existing CUDA atomics */
1150 }
1151
1158 __device__ constexpr auto tryAtomicExchange(const Aesi& value) noexcept -> void {
1159 base.tryAtomicExchange(value.base);
1160 sign = value.sign; /* TODO: Make enum substitution using existing CUDA atomics */
1161 }
1162#endif
1163};
1164
1165/* -------------------------------------------- @name Type-definitions ------------------------------------------- */
1170
1175
1180
1185
1190
1195
1200
1205
1210
1215
1220/* ---------------------------------------------------------------------------------------------------------------- */
1221
1222/* ------------------------------------------ @name Integral conversions ----------------------------------------- */
1229template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1230gpu constexpr auto operator+(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) + value; }
1231
1238template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1239gpu constexpr auto operator-(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) - value; }
1240
1247template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1248gpu constexpr auto operator*(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) * value; }
1249
1256template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1257gpu constexpr auto operator/(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) / value; }
1258
1265template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1266gpu constexpr auto operator%(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) % value; }
1267
1274template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1275gpu constexpr auto operator^(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) ^ value; }
1276
1283template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1284gpu constexpr auto operator&(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) & value; }
1285
1292template <std::size_t bitness, typename Integral> requires (std::is_integral_v<Integral>)
1293gpu constexpr auto operator|(Integral number, const Aesi<bitness>& value) noexcept { return Aesi<bitness>(number) | value; }
1294/* ---------------------------------------------------------------------------------------------------------------- */
1295
1296#endif //AESI_MULTIPRECISION
Long precision unsigned integer with arithmetic operations.
Long precision signed integer.
Definition Aesi.h:67
gpu constexpr friend auto operator%(const Aesi &modulation, const Aesi &modulo) noexcept -> Aesi
Modulo operator.
Definition Aesi.h:573
gpu constexpr auto byteCount() const noexcept -> std::size_t
Get amount of non-empty bytes in number right to left.
Definition Aesi.h:859
gpu constexpr auto operator<=>(const Object &other) const noexcept -> std::strong_ordering
Three-way comparison operator for numbers of different precision and built-in integral types.
Definition Aesi.h:785
gpu constexpr friend auto operator/=(Aesi &division, const Aesi &divisor) noexcept -> Aesi &
Assignment division operator.
Definition Aesi.h:537
gpu constexpr auto swap(Aesi &other) noexcept -> void
Make swap between two objects.
Definition Aesi.h:928
gpu constexpr auto inverse() noexcept -> void
Invertes number's bitness.
Definition Aesi.h:937
gpu constexpr Aesi(const Aeu< bitness > &value)
Unsigned integer conversion.
Definition Aesi.h:150
gpu constexpr auto operator++(int) &noexcept -> Aesi
Postfix increment operator.
Definition Aesi.h:247
gpu constexpr auto operator--(int) &noexcept -> Aesi
Postfix decrement operator.
Definition Aesi.h:267
gpu constexpr Aesi & operator=(const Aesi &other) noexcept=default
Copy assignment operator.
gpu constexpr friend auto operator-=(Aesi &subtraction, const Aesi &subtrahend) noexcept -> Aesi &
Subtraction assignment operator.
Definition Aesi.h:358
gpu constexpr auto operator--() noexcept -> Aesi &
Prefix decrement operator.
Definition Aesi.h:253
gpu constexpr auto compareTo(const Aesi< otherBitness > &value) const noexcept -> Comparison
Different precision comparison operator.
Definition Aesi.h:695
gpu constexpr friend auto operator==(const Aesi &our, const Aesi< otherBitness > &other) noexcept -> bool
Different precision equlity operator.
Definition Aesi.h:642
__device__ constexpr auto tryAtomicSet(const Aesi &value) noexcept -> void
Atomicity-oriented object assignment operator.
Definition Aesi.h:1147
gpu constexpr friend auto operator*(const Aesi &multiplication, const Aesi &factor) noexcept -> Aesi
Multiplication operator.
Definition Aesi.h:438
gpu constexpr auto getString(Char *buffer, std::size_t bufferSize, bool showBase=false, bool hexUppercase=false) const noexcept -> std::size_t
Character buffer output operator.
Definition Aesi.h:1071
gpu constexpr auto operator++() noexcept -> Aesi &
Prefix increment operator.
Definition Aesi.h:233
gpu constexpr friend auto operator%=(Aesi &modulation, const Aesi &modulo) noexcept -> Aesi &
Modulo assignment operator.
Definition Aesi.h:607
gpu constexpr auto operator<=>(const Aesi &other) const noexcept -> std::strong_ordering
Three-way comparison operator.
Definition Aesi.h:764
gpu constexpr Aesi(String &&stringView) noexcept
String / String-view constructor.
Definition Aesi.h:140
gpu constexpr friend auto operator+(const Aesi &addition, const Aesi &addendum) noexcept -> Aesi
Addition operator.
Definition Aesi.h:278
static gpu constexpr auto power2(std::size_t power) noexcept -> Aesi
Fast exponentiation of 2.
Definition Aesi.h:1003
gpu constexpr auto integralCast() const noexcept -> Integral
Cast for built-in integral types.
Definition Aesi.h:1017
gpu constexpr auto precisionCast() const noexcept -> Aesi< newBitness >
Number's precision cast.
Definition Aesi.h:1035
gpu constexpr friend auto operator+=(Aesi &addition, const Aesi &addendum) noexcept -> Aesi &
Addition assignment operator.
Definition Aesi.h:288
gpu constexpr friend auto operator-(const Aesi &subtraction, const Aesi &subtrahend) noexcept -> Aesi
Subtraction operator.
Definition Aesi.h:348
gpu constexpr friend auto operator/(const Aesi &division, const Aesi &divisor) noexcept -> Aesi
Division operator.
Definition Aesi.h:503
gpu constexpr auto setBlock(std::size_t index, block block) noexcept -> void
Set block in number by index starting from the right.
Definition Aesi.h:843
gpu constexpr auto isOdd() const noexcept -> bool
Check whether number is odd.
Definition Aesi.h:873
static gpu constexpr auto getBitness() noexcept -> std::size_t
Get number's precision.
Definition Aesi.h:915
__device__ constexpr auto tryAtomicExchange(const Aesi &value) noexcept -> void
Atomicity-oriented object exchangement operator.
Definition Aesi.h:1158
gpu constexpr auto getBlock(std::size_t index) const noexcept -> block
Get block in number by index starting from the right.
Definition Aesi.h:852
gpu constexpr Aesi(const Char *ptr, std::size_t size) noexcept
Pointer-based character constructor.
Definition Aesi.h:121
gpu constexpr auto isNegative() const noexcept -> bool
Check whether number is negative.
Definition Aesi.h:901
gpu constexpr auto isEven() const noexcept -> bool
Check whether number is even.
Definition Aesi.h:880
gpu constexpr auto isZero() const noexcept -> bool
Check whether number is zero.
Definition Aesi.h:887
gpu constexpr auto filledBlocksNumber() const noexcept -> std::size_t
Get number of non-empty blocks inside object starting from the right.
Definition Aesi.h:908
gpu constexpr auto getByte(std::size_t index) const noexcept -> byte
Get byte in number by index starting from the right.
Definition Aesi.h:835
gpu constexpr auto operator-() const noexcept -> Aesi
Unary minus operator.
Definition Aesi.h:227
gpu constexpr auto getBit(std::size_t index) const noexcept -> bool
Get bit in number by index starting from the right.
Definition Aesi.h:818
gpu constexpr auto squareRoot() const noexcept -> Aesi
Square root.
Definition Aesi.h:991
gpu constexpr auto compareTo(const Aesi &value) const noexcept -> Comparison
Comparison operator.
Definition Aesi.h:705
gpu constexpr auto compareTo(Integral integral) const noexcept -> Comparison
Comparison operator for built-in types.
Definition Aesi.h:659
gpu constexpr auto setByte(std::size_t index, byte byte) noexcept -> void
Set byte in number by index starting from the right.
Definition Aesi.h:826
static gpu constexpr auto totalBlocksNumber() noexcept -> std::size_t
Get the number of blocks (length of array of uint32_t integers) inside object.
Definition Aesi.h:922
gpu constexpr auto isPositive() const noexcept -> bool
Check whether number is positive.
Definition Aesi.h:894
static gpu constexpr auto divide(const Aesi &number, const Aesi &divisor, Aesi &quotient, Aesi &remainder) noexcept -> void
Integral division.
Definition Aesi.h:952
gpu constexpr auto setBit(std::size_t index, bool bit) noexcept -> void
Set bit in number by index starting from the right.
Definition Aesi.h:809
gpu constexpr auto unsignedCast() const noexcept -> Aeu< bitness >
Unsigned cast.
Definition Aesi.h:1057
gpu constexpr Aesi(const Char(&literal)[arrayLength]) noexcept
C-style string literal constructor.
Definition Aesi.h:132
gpu constexpr friend auto operator*=(Aesi &multiplication, const Aesi &factor) noexcept -> Aesi &
Multiplication assignment operator.
Definition Aesi.h:469
gpu constexpr Aesi() noexcept=default
Default constructor.
gpu constexpr auto operator+() const noexcept -> Aesi
Unary plus operator.
Definition Aesi.h:220
gpu constexpr auto bitCount() const noexcept -> std::size_t
Get amount of non-empty bits in number right to left.
Definition Aesi.h:866
Long precision unsigned integer.
Definition Aeu.h:83
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 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
static gpu constexpr auto power2(std::size_t power) noexcept -> Aeu
Fast exponentiation for powers of 2.
Definition Aeu.h:1259
gpu constexpr auto isEven() const noexcept -> bool
Check whether number is even.
Definition Aeu.h:1045
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 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 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 auto isOdd() const noexcept -> bool
Check whether number is odd.
Definition Aeu.h:1038
gpu constexpr auto swap(Aeu &other) noexcept -> void
Make swap between two objects.
Definition Aeu.h:1083
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
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 getBit(std::size_t index) const noexcept -> bool
Get bit in number by index staring from the right.
Definition Aeu.h:926
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