7 #ifndef AMCORE_AMINTEGER_H
8 #define AMCORE_AMINTEGER_H
10 #include <type_traits>
32 template<
typename TIntType>
35 return (x >> (
sizeof(TIntType) * 4));
43 template<
typename TIntType>
46 TIntType res = ((1ULL <<
sizeof(TIntType) * 4) - 1) & x;
58 template<
typename TIntType>
61 static_assert(std::is_integral<TIntType>::value,
"Integral required.");
63 if constexpr (
sizeof(
long long) >=
sizeof(TIntType) * 2) {
64 if constexpr (std::is_signed<TIntType>::value) {
65 long long tresult = (
long long) a * (
long long) b;
66 long long cresult = tresult >> (
sizeof(TIntType) * 8);
67 bool rsign = tresult & (1ULL << (
sizeof(TIntType) * 8 -1));
68 if (cresult == 0 || cresult == -1) {
69 if ((a >= 0 && b >= 0 && !rsign)
70 || (a <= 0 && b <= 0 && !rsign)
71 || (a < 0 && b > 0 && rsign)
72 || (a > 0 && b < 0 && rsign)) {
73 result = (TIntType) tresult;
77 if ((a < 0 && b < 0) || (a > 0 && b > 0)) {
78 result = std::numeric_limits<TIntType>::max();
80 result = std::numeric_limits<TIntType>::min();
84 unsigned long long tresult = (
unsigned long long) a * (
unsigned long long) b;
85 unsigned long long cresult = tresult >> (
sizeof(TIntType) * (
sizeof(
unsigned long long) ==
sizeof(TIntType) ? 0 : 8));
87 result = (TIntType)tresult;
90 result = std::numeric_limits<TIntType>::max();
94 typedef std::conditional_t<std::is_signed<TIntType>::value, TIntType,
typename std::make_unsigned<TIntType>::type> TUIntType;
95 const TUIntType mask = (1ULL <<
sizeof(TIntType) * 4) - 1;
97 TUIntType s0, s11, s12, s21, s22, s3;
100 TUIntType x1 = loa * lob;
107 TUIntType x3 = s11 + loa * hib;
114 if constexpr (std::is_signed<TIntType>::value) {
115 if (((s22 & mask) != 0 || (s3 & mask) != 0)
116 && ((s22 & mask) != (((TUIntType) - 1) & mask) || (s3 & mask) != (((TUIntType) - 1) & mask))) {
118 result = std::numeric_limits<TIntType>::max();
120 result = std::numeric_limits<TIntType>::min();
124 TIntType tresult = s12 << (
sizeof(TIntType) * 4) | s0;
125 if ((a >= 0 && b >= 0 && tresult >= 0)
126 || (a <= 0 && b <= 0 && tresult >= 0)
127 || (a < 0 && b > 0 && tresult < 0)
128 || (a > 0 && b < 0 && tresult < 0)) {
133 result = std::numeric_limits<TIntType>::max();
135 result = std::numeric_limits<TIntType>::min();
139 if (s22 > 0 || s3 > 0) {
140 result = std::numeric_limits<TIntType>::max();
143 result = s12 << (
sizeof(TIntType) * 4) | s0;
157 template<
typename TIntType>
160 static_assert(std::is_integral<TIntType>::value,
"Integral required.");
162 if constexpr ((
sizeof(
long long) >=
sizeof(TIntType) * 2) || std::is_signed<TIntType>::value) {
163 if constexpr (std::is_signed<TIntType>::value) {
164 TIntType tresult = a + b;
165 if (a > 0 && b > 0 && tresult < 0) {
166 result = std::numeric_limits<TIntType>::max();
168 }
else if (a < 0 && b < 0 && tresult > 0) {
169 result = std::numeric_limits<TIntType>::min();
176 unsigned long long tresult = (
unsigned long long) a + (
unsigned long long) b;
177 long long cresult = tresult & (-1LL ^ ((1ULL <<
sizeof(TIntType)*8) - 1));
179 result = std::numeric_limits<TIntType>::max();
182 result = (TIntType)tresult;
186 typedef std::conditional_t<std::is_signed<TIntType>::value, TIntType,
typename std::make_unsigned<TIntType>::type> TUIntType;
188 TUIntType s0, s1, s2;
191 TUIntType x1 = loa + lob;
199 result = std::numeric_limits<TIntType>::max();
202 result = s1 << (
sizeof(TIntType) * 4) | s0;
207 template<
typename TIntType>
208 bool AMIntegerPow(TIntType x,
unsigned int p, TIntType& result)
210 if (p == 0)
return 1;
211 if (p == 1)
return x;
214 if (!AMIntegerPow(x, p/2, tmp)) {
233 template<
typename TIntType>
234 TIntType AMIntegerPowRaw(TIntType x,
unsigned int p)
236 if (p == 0)
return 1;
237 if (p == 1)
return x;
239 int tmp = AMIntegerPowRaw(x, p/2);
243 else return x * tmp * tmp;
249 #endif //AMCORE_AMINTEGER_H