9#ifndef FORTRAN_EVALUATE_INTEGER_H_
10#define FORTRAN_EVALUATE_INTEGER_H_
20#include "flang/Common/bit-population-count.h"
21#include "flang/Common/leading-zero-bit-count.h"
22#include "flang/Evaluate/common.h"
34namespace Fortran::evaluate::value {
37static constexpr int DecimalRange(
int bits) {
39 return static_cast<int>((bits * 301029995664) / 1000000000000);
58template <
int BITS,
bool IS_LITTLE_ENDIAN = isHostLittleEndian,
59 int PARTBITS = BITS <= 32 ? BITS
63 typename PART = HostUnsignedInt<PARTBITS>,
64 typename BIGPART = HostUnsignedInt<PARTBITS * 2>,
int ALIGNMENT = BITS>
67 static constexpr int bits{BITS};
68 static constexpr int partBits{PARTBITS};
70 using BigPart = BIGPART;
71 static_assert(std::is_integral_v<Part>);
72 static_assert(std::is_unsigned_v<Part>);
73 static_assert(std::is_integral_v<BigPart>);
74 static_assert(std::is_unsigned_v<BigPart>);
75 static_assert(CHAR_BIT *
sizeof(BigPart) >= 2 * partBits);
76 static constexpr bool littleEndian{IS_LITTLE_ENDIAN};
79 static constexpr int maxPartBits{CHAR_BIT *
sizeof(Part)};
80 static_assert(partBits > 0 && partBits <= maxPartBits);
81 static constexpr int extraPartBits{maxPartBits - partBits};
82 static constexpr int parts{(bits + partBits - 1) / partBits};
83 static_assert(parts >= 1);
84 static constexpr int extraTopPartBits{
85 extraPartBits + (parts * partBits) - bits};
86 static constexpr int topPartBits{maxPartBits - extraTopPartBits};
87 static_assert(topPartBits > 0 && topPartBits <= partBits);
88 static_assert((parts - 1) * partBits + topPartBits == bits);
89 static constexpr Part partMask{
static_cast<Part
>(~0) >> extraPartBits};
90 static constexpr Part topPartMask{
static_cast<Part
>(~0) >> extraTopPartBits};
91 static constexpr int partsWithAlignment{
92 (ALIGNMENT + partBits - 1) / partBits};
107 bool SignedMultiplicationOverflowed()
const {
108 return lower.IsNegative() ? (upper.POPCNT() != bits) : !upper.IsZero();
110 Integer upper, lower;
114 Integer quotient, remainder;
115 bool divisionByZero, overflow;
120 bool divisionByZero{
false}, overflow{
false}, zeroToZero{
false};
124 constexpr Integer() { Clear(); }
125 constexpr Integer(
const Integer &) =
default;
126 constexpr Integer(Integer &&) =
default;
130 template <
typename INT,
typename = std::enable_if_t<std::is_
integral_v<INT>>>
131 constexpr Integer(INT n) {
132 constexpr int nBits = CHAR_BIT *
sizeof n;
133 if constexpr (nBits < partBits) {
134 if constexpr (std::is_unsigned_v<INT>) {
137 for (
int j{1}; j < parts; ++j) {
144 using SignedPart = std::make_signed_t<Part>;
145 Part p =
static_cast<SignedPart
>(n);
147 if constexpr (parts > 1) {
148 Part signExtension =
static_cast<SignedPart
>(-(n < 0));
149 for (
int j{1}; j < parts; ++j) {
150 SetLEPart(j, signExtension);
158 if constexpr (std::is_unsigned_v<INT>) {
159 for (
int j{0}; j < parts; ++j) {
160 SetLEPart(j,
static_cast<Part
>(n));
161 if constexpr (nBits > partBits) {
170 auto signExtension{std::make_unsigned_t<INT>(n < 0)};
171 signExtension = ~signExtension + 1;
172 static_assert(nBits >= partBits);
173 if constexpr (nBits > partBits) {
174 signExtension <<= nBits - partBits;
175 for (
int j{0}; j < parts; ++j) {
176 SetLEPart(j,
static_cast<Part
>(n));
181 SetLEPart(0,
static_cast<Part
>(n));
182 for (
int j{1}; j < parts; ++j) {
183 SetLEPart(j,
static_cast<Part
>(signExtension));
190 constexpr Integer &operator=(
const Integer &) =
default;
192 constexpr bool operator<(
const Integer &that)
const {
193 return CompareSigned(that) == Ordering::Less;
195 constexpr bool operator<=(
const Integer &that)
const {
196 return CompareSigned(that) != Ordering::Greater;
198 constexpr bool operator==(
const Integer &that)
const {
199 return CompareSigned(that) == Ordering::Equal;
201 constexpr bool operator!=(
const Integer &that)
const {
202 return !(*
this == that);
204 constexpr bool operator>=(
const Integer &that)
const {
205 return CompareSigned(that) != Ordering::Less;
207 constexpr bool operator>(
const Integer &that)
const {
208 return CompareSigned(that) == Ordering::Greater;
212 static constexpr Integer MASKL(
int places) {
215 }
else if (places >= bits) {
218 return MASKR(bits - places).NOT();
223 static constexpr Integer MASKR(
int places) {
224 Integer result{
nullptr};
226 for (; j + 1 < parts && places >= partBits; ++j, places -= partBits) {
227 result.LEPart(j) = partMask;
231 result.LEPart(j++) = partMask >> (partBits - places);
232 }
else if (j + 1 == parts) {
233 if (places >= topPartBits) {
234 result.LEPart(j++) = topPartMask;
236 result.LEPart(j++) = topPartMask >> (topPartBits - places);
240 for (; j < parts; ++j) {
241 result.LEPart(j) = 0;
246 static constexpr ValueWithOverflow Read(
247 const char *&pp, std::uint64_t base = 10,
bool isSigned =
false) {
249 bool overflow{
false};
251 while (*p ==
' ' || *p ==
'\t') {
254 bool negate{*p ==
'-'};
255 if (negate || *p ==
'+') {
256 while (*++p ==
' ' || *p ==
'\t') {
268 for (; std::uint64_t digit = *p; ++p) {
269 if (digit >=
'0' && digit <=
'9' && digit <
'0' + base) {
271 }
else if (base > 10 && digit >=
'A' && digit <
'A' + base - 10) {
273 }
else if (base > 10 && digit >=
'a' && digit <
'a' + base - 10) {
278 Product shifted{result.MultiplyUnsigned(radix)};
279 overflow |= !shifted.upper.IsZero();
280 ValueWithCarry next{shifted.lower.AddUnsigned(Integer{digit})};
281 overflow |= next.carry;
286 result = result.Negate().value;
287 overflow |= isSigned && !result.IsNegative() && !result.IsZero();
289 overflow |= isSigned && result.IsNegative();
291 return {result, overflow};
294 template <
typename FROM>
295 static constexpr ValueWithOverflow ConvertUnsigned(
const FROM &that) {
296 std::uint64_t field{that.ToUInt64()};
297 ValueWithOverflow result{field,
false};
298 if constexpr (bits < 64) {
299 result.overflow = (field >> bits) != 0;
301 for (
int j{64}; j < that.bits && !result.overflow; j += 64) {
302 field = that.SHIFTR(j).ToUInt64();
304 result.overflow = field != 0;
306 result.value = result.value.IOR(Integer{field}.SHIFTL(j));
308 result.overflow = (field >> (bits - j)) != 0;
315 template <
typename FROM>
316 static constexpr ValueWithOverflow ConvertSigned(
const FROM &that) {
317 ValueWithOverflow result{ConvertUnsigned(that)};
318 if constexpr (bits > FROM::bits) {
319 if (that.IsNegative()) {
320 result.value = result.value.IOR(MASKL(bits - FROM::bits));
322 result.overflow =
false;
323 }
else if constexpr (bits < FROM::bits) {
324 auto back{FROM::template ConvertSigned<Integer>(result.value)};
325 result.overflow = back.value.CompareUnsigned(that) != Ordering::Equal;
330 std::string UnsignedDecimal()
const {
331 if constexpr (bits < 4) {
332 char digit =
'0' + ToUInt64();
334 }
else if (IsZero()) {
337 QuotientWithRemainder qr{DivideUnsigned(10)};
338 char digit =
'0' + qr.remainder.ToUInt64();
339 if (qr.quotient.IsZero()) {
342 return qr.quotient.UnsignedDecimal() + digit;
347 std::string SignedDecimal()
const {
349 return std::string{
'-'} + Negate().value.UnsignedDecimal();
351 return UnsignedDecimal();
356 std::string Hexadecimal()
const {
358 int digits{(bits + 3) >> 2};
359 for (
int j{0}; j < digits; ++j) {
360 int pos{(digits - 1 - j) * 4};
361 char nybble = IBITS(pos, 4).ToUInt64();
362 if (nybble != 0 || !result.empty() || j + 1 == digits) {
363 char digit =
'0' + nybble;
365 digit +=
'a' - (
'9' + 1);
373 static constexpr int DIGITS{bits - 1};
374 static constexpr Integer HUGE() {
return MASKR(bits - 1); }
375 static constexpr Integer Least() {
return MASKL(1); }
376 static constexpr int RANGE{DecimalRange(bits - 1)};
377 static constexpr int UnsignedRANGE{DecimalRange(bits)};
379 constexpr bool IsZero()
const {
380 for (
int j{0}; j < parts; ++j) {
388 constexpr bool IsNegative()
const {
389 return (LEPart(parts - 1) >> (topPartBits - 1)) & 1;
392 constexpr Ordering CompareToZeroSigned()
const {
394 return Ordering::Less;
395 }
else if (IsZero()) {
396 return Ordering::Equal;
398 return Ordering::Greater;
404 constexpr int LEADZ()
const {
405 if (LEPart(parts - 1) != 0) {
406 int lzbc{common::LeadingZeroBitCount(LEPart(parts - 1))};
407 return lzbc - extraTopPartBits;
409 int upperZeroes{topPartBits};
410 for (
int j{1}; j < parts; ++j) {
411 if (Part p{LEPart(parts - 1 - j)}) {
412 int lzbc{common::LeadingZeroBitCount(p)};
413 return upperZeroes + lzbc - extraPartBits;
415 upperZeroes += partBits;
421 constexpr int POPCNT()
const {
423 for (
int j{0}; j < parts; ++j) {
424 count += common::BitPopulationCount(part_[j]);
430 constexpr bool POPPAR()
const {
return POPCNT() & 1; }
432 constexpr int TRAILZ()
const {
433 auto minus1{AddUnsigned(MASKR(bits))};
438 return IEOR(minus1.value).POPCNT() - 1;
442 constexpr bool BTEST(
int pos)
const {
443 if (pos < 0 || pos >= bits) {
446 return (LEPart(pos / partBits) >> (pos % partBits)) & 1;
450 constexpr Ordering CompareUnsigned(
const Integer &y)
const {
451 for (
int j{parts}; j-- > 0;) {
452 if (LEPart(j) > y.LEPart(j)) {
453 return Ordering::Greater;
455 if (LEPart(j) < y.LEPart(j)) {
456 return Ordering::Less;
459 return Ordering::Equal;
462 constexpr bool BGE(
const Integer &y)
const {
463 return CompareUnsigned(y) != Ordering::Less;
465 constexpr bool BGT(
const Integer &y)
const {
466 return CompareUnsigned(y) == Ordering::Greater;
468 constexpr bool BLE(
const Integer &y)
const {
return !BGT(y); }
469 constexpr bool BLT(
const Integer &y)
const {
return !BGE(y); }
471 constexpr Ordering CompareSigned(
const Integer &y)
const {
472 bool isNegative{IsNegative()};
473 if (isNegative != y.IsNegative()) {
474 return isNegative ? Ordering::Less : Ordering::Greater;
476 return CompareUnsigned(y);
479 template <
typename UINT = std::u
int64_t>
constexpr UINT ToUInt()
const {
481 std::size_t filled{partBits};
482 constexpr std::size_t maxBits{CHAR_BIT *
sizeof n};
483 for (
int j{1}; filled < maxBits && j < parts; ++j, filled += partBits) {
484 n |= UINT{LEPart(j)} << filled;
489 template <
typename SINT = std::
int64_t,
typename UINT = std::u
int64_t>
490 constexpr SINT ToSInt()
const {
491 SINT n = ToUInt<UINT>();
492 constexpr std::size_t maxBits{CHAR_BIT *
sizeof n};
493 if constexpr (bits < maxBits) {
496 auto u{std::make_unsigned_t<SINT>(ToUInt())};
497 u = (u >> (bits - 1)) << (bits - 1);
499 n |=
static_cast<SINT
>(u);
504 constexpr std::uint64_t ToUInt64()
const {
return ToUInt<std::uint64_t>(); }
506 constexpr std::int64_t ToInt64()
const {
507 return ToSInt<std::int64_t, std::uint64_t>();
511 constexpr Integer NOT()
const {
512 Integer result{
nullptr};
513 for (
int j{0}; j < parts; ++j) {
514 result.SetLEPart(j, ~LEPart(j));
522 constexpr ValueWithOverflow Negate()
const {
523 Integer result{
nullptr};
525 for (
int j{0}; j + 1 < parts; ++j) {
526 Part newCarry{LEPart(j) == 0 && carry};
527 result.SetLEPart(j, ~LEPart(j) + carry);
530 Part top{LEPart(parts - 1)};
531 result.SetLEPart(parts - 1, ~top + carry);
532 bool overflow{top != 0 && result.LEPart(parts - 1) == top};
533 return {result, overflow};
536 constexpr ValueWithOverflow ABS()
const {
540 return {*
this,
false};
546 constexpr Integer ISHFT(
int count)
const {
548 return SHIFTR(-count);
550 return SHIFTL(count);
555 constexpr Integer SHIFTL(
int count)
const {
559 Integer result{
nullptr};
560 int shiftParts{count / partBits};
561 int bitShift{count - partBits * shiftParts};
564 for (; j >= shiftParts; --j) {
565 result.SetLEPart(j, LEPart(j - shiftParts));
567 for (; j >= 0; --j) {
568 result.LEPart(j) = 0;
571 for (; j > shiftParts; --j) {
573 ((LEPart(j - shiftParts) << bitShift) |
574 (LEPart(j - shiftParts - 1) >> (partBits - bitShift))));
576 if (j == shiftParts) {
577 result.SetLEPart(j, LEPart(0) << bitShift);
580 for (; j >= 0; --j) {
581 result.LEPart(j) = 0;
592 constexpr Integer ISHFTC(
int count,
int size = bits)
const {
593 if (count == 0 || size <= 0) {
603 int middleBits{size - count}, leastBits{count};
606 leastBits = size + count;
609 return SHIFTL(leastBits).IOR(SHIFTR(middleBits));
611 Integer unchanged{IAND(MASKL(bits - size))};
612 Integer middle{IAND(MASKR(middleBits)).SHIFTL(leastBits)};
613 Integer least{SHIFTR(middleBits).IAND(MASKR(leastBits))};
614 return unchanged.IOR(middle).IOR(least);
618 constexpr Integer SHIFTLWithFill(
const Integer &fill,
int count)
const {
621 }
else if (count >= 2 * bits) {
623 }
else if (count > bits) {
624 return fill.SHIFTL(count - bits);
625 }
else if (count == bits) {
628 return SHIFTL(count).IOR(fill.SHIFTR(bits - count));
632 constexpr Integer SHIFTRWithFill(
const Integer &fill,
int count)
const {
635 }
else if (count >= 2 * bits) {
637 }
else if (count > bits) {
638 return fill.SHIFTR(count - bits);
639 }
else if (count == bits) {
642 return SHIFTR(count).IOR(fill.SHIFTL(bits - count));
646 constexpr Integer DSHIFTL(
const Integer &fill,
int count)
const {
648 return SHIFTLWithFill(fill, count);
651 constexpr Integer DSHIFTR(
const Integer &value,
int count)
const {
653 return value.SHIFTRWithFill(*
this, count);
657 constexpr Integer SHIFTR(
int count)
const {
661 Integer result{
nullptr};
662 int shiftParts{count / partBits};
663 int bitShift{count - partBits * shiftParts};
666 for (; j + shiftParts < parts; ++j) {
667 result.LEPart(j) = LEPart(j + shiftParts);
669 for (; j < parts; ++j) {
670 result.LEPart(j) = 0;
673 for (; j + shiftParts + 1 < parts; ++j) {
675 (LEPart(j + shiftParts) >> bitShift) |
676 (LEPart(j + shiftParts + 1) << (partBits - bitShift)));
678 if (j + shiftParts + 1 == parts) {
679 result.LEPart(j++) = LEPart(parts - 1) >> bitShift;
681 for (; j < parts; ++j) {
682 result.LEPart(j) = 0;
691 constexpr Integer SHIFTA(
int count)
const {
694 }
else if (IsNegative()) {
695 return SHIFTR(count).IOR(MASKL(count));
697 return SHIFTR(count);
702 constexpr Integer IBCLR(
int pos)
const {
703 if (pos < 0 || pos >= bits) {
706 Integer result{*
this};
707 result.LEPart(pos / partBits) &= ~(Part{1} << (pos % partBits));
713 constexpr Integer IBSET(
int pos)
const {
714 if (pos < 0 || pos >= bits) {
717 Integer result{*
this};
718 result.LEPart(pos / partBits) |= Part{1} << (pos % partBits);
724 constexpr Integer IBITS(
int pos,
int size)
const {
725 return SHIFTR(pos).IAND(MASKR(size));
728 constexpr Integer IAND(
const Integer &y)
const {
729 Integer result{
nullptr};
730 for (
int j{0}; j < parts; ++j) {
731 result.LEPart(j) = LEPart(j) & y.LEPart(j);
736 constexpr Integer IOR(
const Integer &y)
const {
737 Integer result{
nullptr};
738 for (
int j{0}; j < parts; ++j) {
739 result.LEPart(j) = LEPart(j) | y.LEPart(j);
744 constexpr Integer IEOR(
const Integer &y)
const {
745 Integer result{
nullptr};
746 for (
int j{0}; j < parts; ++j) {
747 result.LEPart(j) = LEPart(j) ^ y.LEPart(j);
752 constexpr Integer MERGE_BITS(
const Integer &y,
const Integer &mask)
const {
753 return IAND(mask).IOR(y.IAND(mask.NOT()));
756 constexpr Integer MAX(
const Integer &y)
const {
757 if (CompareSigned(y) == Ordering::Less) {
764 constexpr Integer MIN(
const Integer &y)
const {
765 if (CompareSigned(y) == Ordering::Less) {
773 constexpr ValueWithCarry AddUnsigned(
774 const Integer &y,
bool carryIn =
false)
const {
775 Integer sum{
nullptr};
776 BigPart carry{carryIn};
777 for (
int j{0}; j + 1 < parts; ++j) {
779 carry += y.LEPart(j);
780 sum.SetLEPart(j, carry);
783 carry += LEPart(parts - 1);
784 carry += y.LEPart(parts - 1);
785 sum.SetLEPart(parts - 1, carry);
786 return {sum, carry > topPartMask};
789 constexpr ValueWithOverflow AddSigned(
const Integer &y)
const {
790 bool isNegative{IsNegative()};
791 bool sameSign{isNegative == y.IsNegative()};
792 ValueWithCarry sum{AddUnsigned(y)};
793 bool overflow{sameSign && sum.value.IsNegative() != isNegative};
794 return {sum.value, overflow};
797 constexpr ValueWithOverflow SubtractSigned(
const Integer &y)
const {
798 bool isNegative{IsNegative()};
799 bool sameSign{isNegative == y.IsNegative()};
800 ValueWithCarry diff{AddUnsigned(y.Negate().value)};
801 bool overflow{!sameSign && diff.value.IsNegative() != isNegative};
802 return {diff.value, overflow};
806 constexpr ValueWithOverflow DIM(
const Integer &y)
const {
807 if (CompareSigned(y) != Ordering::Greater) {
810 return SubtractSigned(y);
814 constexpr ValueWithOverflow SIGN(
bool toNegative)
const {
815 if (toNegative == IsNegative()) {
816 return {*
this,
false};
817 }
else if (toNegative) {
824 constexpr ValueWithOverflow SIGN(
const Integer &sign)
const {
825 return SIGN(sign.IsNegative());
828 constexpr Product MultiplyUnsigned(
const Integer &y)
const {
829 Part product[2 * parts]{};
830 for (
int j{0}; j < parts; ++j) {
831 if (Part xpart{LEPart(j)}) {
832 for (
int k{0}; k < parts; ++k) {
833 if (Part ypart{y.LEPart(k)}) {
836#if defined __GNUC__ && __GNUC__ < 8 || __GNUC__ >= 12
839 for (
int to{j + k}; xy != 0 && to < (2 * parts); ++to) {
841 for (
int to{j + k}; xy != 0; ++to) {
844 product[to] = xy & partMask;
851 Integer upper{
nullptr}, lower{
nullptr};
852 for (
int j{0}; j < parts; ++j) {
853 lower.LEPart(j) = product[j];
854 upper.LEPart(j) = product[j + parts];
856 if constexpr (topPartBits < partBits) {
857 upper = upper.SHIFTL(partBits - topPartBits);
858 upper.LEPart(0) |= lower.LEPart(parts - 1) >> topPartBits;
859 lower.LEPart(parts - 1) &= topPartMask;
861 return {upper, lower};
864 constexpr Product MultiplySigned(
const Integer &y)
const {
865 bool yIsNegative{y.IsNegative()};
868 absy = y.Negate().value;
870 bool isNegative{IsNegative()};
873 absx = Negate().value;
875 Product product{absx.MultiplyUnsigned(absy)};
876 if (isNegative != yIsNegative) {
877 product.lower = product.lower.NOT();
878 product.upper = product.upper.NOT();
880 auto incremented{product.lower.AddUnsigned(one)};
881 product.lower = incremented.value;
882 if (incremented.carry) {
883 product.upper = product.upper.AddUnsigned(one).value;
889 constexpr QuotientWithRemainder DivideUnsigned(
const Integer &divisor)
const {
890 if (divisor.IsZero()) {
891 return {MASKR(bits), Integer{},
true,
false};
893 int bitsDone{LEADZ()};
894 Integer top{SHIFTL(bitsDone)};
895 Integer quotient, remainder;
896 for (; bitsDone < bits; ++bitsDone) {
897 auto doubledTop{top.AddUnsigned(top)};
898 top = doubledTop.value;
899 remainder = remainder.AddUnsigned(remainder, doubledTop.carry).value;
900 bool nextBit{remainder.CompareUnsigned(divisor) != Ordering::Less};
901 quotient = quotient.AddUnsigned(quotient, nextBit).value;
903 remainder = remainder.SubtractSigned(divisor).value;
906 return {quotient, remainder,
false,
false};
912 constexpr QuotientWithRemainder DivideSigned(Integer divisor)
const {
913 bool dividendIsNegative{IsNegative()};
914 bool negateQuotient{dividendIsNegative};
915 Ordering divisorOrdering{divisor.CompareToZeroSigned()};
916 if (divisorOrdering == Ordering::Less) {
917 negateQuotient = !negateQuotient;
918 auto negated{divisor.Negate()};
919 if (negated.overflow) {
921 if (CompareUnsigned(divisor) == Ordering::Equal) {
922 return {MASKR(1), Integer{},
false, bits <= 1};
924 return {Integer{}, *
this,
false,
false};
927 divisor = negated.value;
928 }
else if (divisorOrdering == Ordering::Equal) {
930 if (dividendIsNegative) {
931 return {MASKL(1), Integer{},
true,
false};
933 return {MASKR(bits - 1), Integer{},
true,
false};
936 Integer dividend{*
this};
937 if (dividendIsNegative) {
938 auto negated{Negate()};
939 if (negated.overflow) {
942 if (divisorOrdering == Ordering::Less &&
943 divisor.CompareUnsigned(Integer{1}) == Ordering::Equal) {
945 return {*
this, Integer{},
false,
true};
948 dividend = negated.value;
953 QuotientWithRemainder result{dividend.DivideUnsigned(divisor)};
954 if (negateQuotient) {
955 result.quotient = result.quotient.Negate().value;
957 if (dividendIsNegative) {
958 result.remainder = result.remainder.Negate().value;
965 constexpr ValueWithOverflow MODULO(
const Integer &divisor)
const {
966 bool negativeDivisor{divisor.IsNegative()};
967 bool distinctSigns{IsNegative() != negativeDivisor};
968 QuotientWithRemainder divided{DivideSigned(divisor)};
969 if (distinctSigns && !divided.remainder.IsZero()) {
970 return {divided.remainder.AddUnsigned(divisor).value, divided.overflow};
972 return {divided.remainder, divided.overflow};
976 constexpr PowerWithErrors Power(
const Integer &exponent)
const {
977 PowerWithErrors result{1,
false,
false,
false};
978 if (exponent.IsZero()) {
985 result.zeroToZero = IsZero();
986 }
else if (exponent.IsNegative()) {
988 result.divisionByZero =
true;
989 result.power = MASKR(bits - 1);
990 }
else if (CompareSigned(Integer{1}) == Ordering::Equal) {
991 result.power = *
this;
992 }
else if (CompareSigned(Integer{-1}) == Ordering::Equal) {
993 if (exponent.BTEST(0)) {
994 result.power = *
this;
997 result.power.Clear();
1000 Integer shifted{*
this};
1001 Integer pow{exponent};
1002 int nbits{bits - pow.LEADZ()};
1003 for (
int j{0}; j < nbits; ++j) {
1005 Product product{result.power.MultiplySigned(shifted)};
1006 result.power = product.lower;
1007 result.overflow |= product.SignedMultiplicationOverflowed();
1009 if (j + 1 < nbits) {
1010 Product squared{shifted.MultiplySigned(shifted)};
1011 result.overflow |= squared.SignedMultiplicationOverflowed();
1012 shifted = squared.lower;
1023 constexpr Integer(std::nullptr_t) {}
1026 constexpr const Part &LEPart(
int part)
const {
1027 if constexpr (littleEndian) {
1030 return part_[parts - 1 - part];
1034 constexpr Part &LEPart(
int part) {
1035 if constexpr (littleEndian) {
1038 return part_[parts - 1 - part];
1042 constexpr void SetLEPart(
int part, Part x) {
1043 LEPart(part) = x & PartMask(part);
1046 static constexpr Part PartMask(
int part) {
1047 return part == parts - 1 ? topPartMask : partMask;
1050 constexpr void Clear() {
1051 for (
int j{0}; j < parts; ++j) {
1056 Part part_[partsWithAlignment]{};
1059extern template class Integer<8>;
1060extern template class Integer<16>;
1061extern template class Integer<32>;
1062extern template class Integer<64>;
1063using X87IntegerContainer =
1064 Integer<80, isHostLittleEndian, 16, std::uint16_t, std::uint32_t, 128>;
1065extern template class Integer<80, isHostLittleEndian, 16, std::uint16_t,
1066 std::uint32_t, 128>;
1067extern template class Integer<128>;
Definition: integer.h:118
Definition: integer.h:106
Definition: integer.h:113
Definition: integer.h:101