28 #ifndef LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H 29 #define LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H 39 #include <type_traits> 43 #include "math/interface.h" 44 #include "math/nbtheory.h" 45 #include "utils/debug.h" 47 #include "utils/inttypes.h" 48 #include "utils/memory.h" 49 #include "utils/palisadebase64.h" 50 #include "utils/serializable.h" 61 #define NATIVEINT_DO_CHECKS false 63 using U32BITS = uint32_t;
64 using U64BITS = uint64_t;
65 #if defined(HAVE_INT128) 66 using U128BITS =
unsigned __int128;
83 template <
typename utype>
85 using DoubleType = void;
86 using SignedType = void;
95 using DoubleType = uint64_t;
96 using SignedType = int32_t;
105 #if defined(HAVE_INT128) 106 using DoubleType = __uint128_t;
108 using DoubleType = uint64_t;
110 using SignedType = int64_t;
113 #if defined(HAVE_INT128) 116 using DoubleType = __uint128_t;
117 using SignedType = __int128;
126 template <
typename NativeInt>
130 using Integer = NativeInt;
131 using DNativeInt =
typename DoubleDataType<NativeInt>::DoubleType;
132 using SignedNativeInt =
typename DoubleDataType<NativeInt>::SignedType;
139 inline std::string ConvertToString() {
140 std::string ret(
"hi [");
169 : m_value(
std::move(val.m_value)) {}
189 template <
typename T = NativeInt>
191 typename std::enable_if<!std::is_same<T, int16_t>::value,
195 template <
typename T = NativeInt>
197 typename std::enable_if<!std::is_same<T, uint16_t>::value,
201 template <
typename T = NativeInt>
203 typename std::enable_if<!std::is_same<T, int32_t>::value,
207 template <
typename T = NativeInt>
209 typename std::enable_if<!std::is_same<T, uint32_t>::value,
213 template <
typename T = NativeInt>
216 typename std::enable_if<!std::is_same<T, long>::value,
bool>::type =
true)
219 template <
typename T = NativeInt>
221 typename std::enable_if<!std::is_same<T, unsigned long>::value,
225 template <
typename T = NativeInt>
227 typename std::enable_if<!std::is_same<T, long long>::value,
231 template <
typename T = NativeInt>
233 unsigned long long init,
234 typename std::enable_if<!std::is_same<T, unsigned long long>::value,
238 #if defined(HAVE_INT128) 239 template <
typename T = NativeInt>
241 unsigned __int128 val,
242 typename std::enable_if<!std::is_same<T, unsigned __int128>::value,
246 template <
typename T = NativeInt>
248 typename std::enable_if<!std::is_same<T, __int128>::value,
259 : m_value(val.ConvertToInt()) {}
267 __attribute__((deprecated(
"Cannot construct from a double")));
278 this->m_value = val.m_value;
289 this->m_value = val.m_value;
323 void SetValue(
const std::string &strval) { AssignVal(strval); }
348 return NATIVEINT_DO_CHECKS ? AddCheck(b) : AddFast(b);
358 return NATIVEINT_DO_CHECKS ? AddEqCheck(b) : AddEqFast(b);
369 NativeInt oldv = m_value;
370 m_value += b.m_value;
371 if (m_value < oldv) {
385 m_value += b.m_value;
396 return NATIVEINT_DO_CHECKS ? SubCheck(b) : SubFast(b);
406 return m_value <= b.m_value ? 0 : m_value - b.m_value;
416 return m_value - b.m_value;
426 return NATIVEINT_DO_CHECKS ? SubEqCheck(b) : SubEqFast(b);
437 m_value = m_value <= b.m_value ? 0 : m_value - b.m_value;
449 m_value -= b.m_value;
464 return NATIVEINT_DO_CHECKS ? MulCheck(b) : MulFast(b);
474 NativeInt prod = m_value * b.m_value;
475 if (prod > 0 && (prod < m_value || prod < b.m_value))
487 return m_value * b.m_value;
497 return NATIVEINT_DO_CHECKS ? MulEqCheck(b) : MulEqFast(b);
508 NativeInt oldval = m_value;
509 m_value *= b.m_value;
510 if (m_value < oldval) {
524 m_value *= b.m_value;
536 return this->m_value / b.m_value;
547 this->m_value /= b.m_value;
568 return tmp * tmp * (*this);
591 (*this) *= (tmp * tmp);
621 this->DivideAndRoundEq(q);
633 template <
typename T = NativeInt>
636 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
638 DNativeInt xD = m_value;
639 DNativeInt pD = p.m_value;
640 DNativeInt qD = q.m_value;
644 template <
typename T = NativeInt>
647 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
649 NativeInt xD = m_value;
650 NativeInt pD = p.m_value;
651 NativeInt qD = q.m_value;
663 template <
typename T = NativeInt>
666 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
668 DNativeInt xD = m_value;
669 DNativeInt pD = p.m_value;
670 DNativeInt qD = q.m_value;
674 template <
typename T = NativeInt>
677 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
679 NativeInt xD = m_value;
680 NativeInt pD = p.m_value;
681 NativeInt qD = q.m_value;
696 NativeInt ans = m_value / q.m_value;
697 NativeInt rem = m_value % q.m_value;
698 NativeInt halfQ = q.m_value >> 1;
699 if (!(rem <= halfQ)) {
713 return *
this = this->DivideAndRound(q);
725 return m_value % modulus.m_value;
735 m_value %= modulus.m_value;
744 template <
typename T = NativeInt>
746 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
749 temp <<= 2 * this->GetMSB() + 3;
750 return NativeInt(temp / DNativeInt(this->m_value));
753 template <
typename T = NativeInt>
755 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
758 temp <<= 2 * this->GetMSB() + 3;
771 template <
typename T = NativeInt>
774 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
777 tmp1.lo = this->m_value;
779 DNativeInt tmp(this->m_value);
781 long n = modulus.
GetMSB();
786 NativeInt ql = RShiftD(tmp1, n + beta);
787 MultD(ql, mu.m_value, tmp1);
788 DNativeInt q = GetD(tmp1);
793 tmp -= q * DNativeInt(modulus.m_value);
796 ans.m_value = NativeInt(tmp);
799 if (ans.m_value > modulus.m_value) {
800 ans.m_value -= modulus.m_value;
805 template <
typename T = NativeInt>
807 typename std::enable_if<std::is_same<T, DNativeInt>::value,
808 bool>::type =
true)
const {
810 prod.lo = this->m_value;
814 long n = modulus.
GetMSB();
818 NativeInt ql = RShiftD(prod, n + beta);
819 MultD(ql, mu.m_value, prod);
821 ql = RShiftD(prod, alpha - beta);
822 MultD(ql, modulus.m_value, prod);
823 SubtractD(result, prod);
827 if (ans.m_value > modulus.m_value) {
828 ans.m_value -= modulus.m_value;
842 template <
typename T = NativeInt>
845 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
848 tmp1.lo = this->m_value;
850 DNativeInt tmp(this->m_value);
852 long n = modulus.
GetMSB();
857 NativeInt ql = RShiftD(tmp1, n + beta);
858 MultD(ql, mu.m_value, tmp1);
859 DNativeInt q = GetD(tmp1);
864 tmp -= q * DNativeInt(modulus.m_value);
866 this->m_value = NativeInt(tmp);
869 if (this->m_value > modulus.m_value) {
870 this->m_value -= modulus.m_value;
875 template <
typename T = NativeInt>
878 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
881 prod.lo = this->m_value;
885 long n = modulus.
GetMSB();
889 NativeInt ql = RShiftD(prod, n + beta);
890 MultD(ql, mu.m_value, prod);
892 ql = RShiftD(prod, alpha - beta);
893 MultD(ql, modulus.m_value, prod);
894 SubtractD(result, prod);
896 this->m_value = result.lo;
898 if (this->m_value > modulus.m_value) {
899 this->m_value -= modulus.m_value;
913 NativeInt mod = modulus.m_value;
914 NativeInt op1 = this->m_value;
915 NativeInt op2 = b.m_value;
938 NativeInt mod = modulus.m_value;
939 NativeInt op2 = b.m_value;
940 if (this->m_value >= mod) {
941 this->m_value %= mod;
946 this->m_value += op2;
947 if (this->m_value >= mod) {
948 this->m_value -= mod;
962 NativeInt r = this->m_value + b.m_value;
963 if (r >= modulus.m_value) {
964 r -= modulus.m_value;
977 this->m_value += b.m_value;
978 if (this->m_value >= modulus.m_value) {
979 this->m_value -= modulus.m_value;
994 NativeInt mod(modulus.m_value);
997 if (av.m_value >= mod) {
998 av.
ModEq(modulus, mu);
1000 if (bv.m_value >= mod) {
1001 bv.
ModEq(modulus, mu);
1003 av.m_value += bv.m_value;
1004 if (av.m_value >= mod) {
1021 NativeInt mod(modulus.m_value);
1023 if (this->m_value >= mod) {
1024 this->ModEq(modulus, mu);
1026 if (bv.m_value >= mod) {
1027 bv.
ModEq(modulus, mu);
1029 this->m_value += bv.m_value;
1030 if (this->m_value >= mod) {
1031 this->m_value -= mod;
1045 NativeInt mod(modulus.m_value);
1046 NativeInt av(this->m_value);
1047 NativeInt bv(b.m_value);
1074 NativeInt mod(modulus.m_value);
1075 NativeInt bv(b.m_value);
1077 if (this->m_value >= mod) {
1078 this->m_value %= mod;
1085 if (this->m_value >= bv) {
1086 this->m_value -= bv;
1088 this->m_value += (mod - bv);
1102 NativeInt mod(modulus.m_value);
1103 NativeInt av(this->m_value);
1104 NativeInt bv(b.m_value);
1123 if (this->m_value >= b.m_value) {
1124 this->m_value -= b.m_value;
1126 this->m_value += (modulus.m_value - b.m_value);
1141 NativeInt mod(modulus.m_value);
1144 if (av.m_value >= mod) {
1145 av.
ModEq(modulus, mu);
1147 if (bv.m_value >= mod) {
1148 bv.
ModEq(modulus, mu);
1151 if (av.m_value >= bv.m_value) {
1152 av.m_value -= bv.m_value;
1154 av.m_value += (mod - bv.m_value);
1171 NativeInt mod(modulus.m_value);
1172 if (this->m_value >= mod) {
1173 this->ModEq(modulus, mu);
1175 if (bv.m_value >= mod) {
1176 bv.
ModEq(modulus, mu);
1179 if (this->m_value >= bv.m_value) {
1180 this->m_value -= bv.m_value;
1182 this->m_value += (mod - bv.m_value);
1194 template <
typename T = NativeInt>
1197 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1199 NativeInt aval = this->m_value;
1200 NativeInt bval = b.m_value;
1201 NativeInt mod = modulus.m_value;
1208 DNativeInt av(aval);
1209 DNativeInt bv(bval);
1210 DNativeInt result = av * bv;
1211 DNativeInt dmod(mod);
1212 if (result >= dmod) {
1218 template <
typename T = NativeInt>
1221 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1227 a.
ModEq(modulus, mu);
1230 bW.
ModEq(modulus, mu);
1232 return a.
ModMul(bW, modulus, mu);
1242 template <
typename T = NativeInt>
1245 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1247 NativeInt bval = b.m_value;
1248 NativeInt mod = modulus.m_value;
1249 if (this->m_value > mod) {
1250 this->m_value %= mod;
1255 DNativeInt av(m_value);
1256 DNativeInt bv(bval);
1257 DNativeInt result = av * bv;
1258 DNativeInt dmod(mod);
1259 if (result >= dmod) {
1266 template <
typename T = NativeInt>
1269 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1273 if (*
this > modulus) {
1277 bW.ModEq(modulus, mu);
1279 ModMulEq(bW, modulus, mu);
1306 template <
typename T = NativeInt>
1310 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1314 if (this->m_value > modulus.m_value) {
1315 this->ModEq(modulus, mu);
1317 if (bb.m_value > modulus.m_value) {
1318 bb.
ModEq(modulus, mu);
1322 MultD(this->m_value, b.m_value, prod1);
1323 DNativeInt prod = GetD(prod1);
1325 long n = modulus.
GetMSB();
1330 NativeInt ql = RShiftD(prod1, n + beta);
1331 MultD(ql, mu.m_value, prod1);
1332 DNativeInt q = GetD(prod1);
1337 prod -= q * DNativeInt(modulus.m_value);
1339 this->m_value = NativeInt(prod);
1342 if (this->m_value > modulus.m_value) {
1343 this->m_value -= modulus.m_value;
1348 template <
typename T = NativeInt>
1352 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1356 if (this->m_value > modulus.m_value) {
1357 this->ModEq(modulus, mu);
1359 if (bb.m_value > modulus.m_value) {
1360 bb.
ModEq(modulus, mu);
1364 MultD(this->m_value, b.m_value, prod1);
1367 long n = modulus.
GetMSB();
1371 NativeInt ql = RShiftD(prod1, n + beta);
1372 MultD(ql, mu.m_value, prod1);
1375 ql = RShiftD(prod1, alpha - beta);
1376 MultD(ql, modulus.m_value, q);
1379 this->m_value = prod.lo;
1382 if (this->m_value > modulus.m_value) {
1383 this->m_value -= modulus.m_value;
1395 template <
typename T = NativeInt>
1398 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1400 DNativeInt av(m_value);
1401 DNativeInt bv(b.m_value);
1402 DNativeInt result = av * bv;
1403 DNativeInt mod(modulus.m_value);
1404 if (result >= mod) {
1410 template <
typename T = NativeInt>
1413 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1419 a.
ModEq(modulus, mu);
1422 bW.
ModEq(modulus, mu);
1437 return *
this = this->ModMulFast(b, modulus);
1465 template <
typename T = NativeInt>
1469 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1474 MultD(ans.m_value, b.m_value, prod1);
1475 DNativeInt prod = GetD(prod1);
1478 long n = modulus.
GetMSB();
1483 NativeInt ql = RShiftD(q0, n + beta);
1484 MultD(ql, mu.m_value, q0);
1485 DNativeInt q = GetD(q0);
1490 prod -= q * DNativeInt(modulus.m_value);
1492 ans.m_value = NativeInt(prod);
1495 if (ans.m_value > modulus.m_value) {
1496 ans.m_value -= modulus.m_value;
1501 template <
typename T = NativeInt>
1505 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1510 MultD(ans.m_value, b.m_value, prod1);
1513 long n = modulus.
GetMSB();
1517 NativeInt ql = RShiftD(prod1, n + beta);
1518 MultD(ql, mu.m_value, prod1);
1521 ql = RShiftD(prod1, alpha - beta);
1522 MultD(ql, modulus.m_value, q);
1525 ans.m_value = prod.lo;
1528 if (ans.m_value > modulus.m_value) {
1529 ans.m_value -= modulus.m_value;
1543 template <
typename T = NativeInt>
1547 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1550 MultD(this->m_value, b.m_value, prod1);
1551 DNativeInt prod = GetD(prod1);
1554 long n = modulus.
GetMSB();
1559 NativeInt ql = RShiftD(q0, n + beta);
1560 MultD(ql, mu.m_value, q0);
1561 DNativeInt q = GetD(q0);
1566 prod -= q * DNativeInt(modulus.m_value);
1568 this->m_value = NativeInt(prod);
1571 if (this->m_value > modulus.m_value) {
1572 this->m_value -= modulus.m_value;
1577 template <
typename T = NativeInt>
1581 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1584 MultD(this->m_value, b.m_value, prod1);
1587 long n = modulus.
GetMSB();
1591 NativeInt ql = RShiftD(prod1, n + beta);
1592 MultD(ql, mu.m_value, prod1);
1595 ql = RShiftD(prod1, alpha - beta);
1596 MultD(ql, modulus.m_value, q);
1599 this->m_value = prod.lo;
1602 if (this->m_value > modulus.m_value) {
1603 this->m_value -= modulus.m_value;
1623 template <
typename T = NativeInt>
1626 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1628 DNativeInt w = DNativeInt(this->m_value) << MaxBits();
1629 return NativeInt(w / DNativeInt(modulus.m_value));
1632 template <
typename T = NativeInt>
1635 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1653 NativeInt q = MultDHi(this->m_value, bInv.m_value);
1654 NativeInt yprime = this->m_value * b.m_value - q * modulus.m_value;
1655 return SignedNativeInt(yprime) - SignedNativeInt(modulus.m_value) >= 0
1656 ? yprime - modulus.m_value
1672 NativeInt q = MultDHi(this->m_value, bInv.m_value);
1673 NativeInt yprime = this->m_value * b.m_value - q * modulus.m_value;
1675 SignedNativeInt(yprime) - SignedNativeInt(modulus.m_value) >= 0
1676 ? yprime - modulus.m_value
1688 template <
typename T = NativeInt>
1691 typename std::enable_if<!std::is_same<T, DNativeInt>::value,
bool>::type =
1693 DNativeInt exp(b.m_value);
1694 DNativeInt product(1);
1695 DNativeInt modulus(mod.m_value);
1696 DNativeInt mid(m_value % mod.m_value);
1697 const DNativeInt ZERO(0);
1698 const DNativeInt ONE(1);
1699 const DNativeInt TWO(2);
1702 if (exp % TWO == ONE) {
1703 product = product * mid;
1707 if (product >= modulus) {
1708 product = product % modulus;
1719 mid = mid % modulus;
1724 template <
typename T = NativeInt>
1727 typename std::enable_if<std::is_same<T, DNativeInt>::value,
bool>::type =
1739 if (exp % TWO == ONE) {
1764 *
this = ModExp(b, mod);
1775 NativeInt modulus = mod.m_value;
1776 NativeInt a = m_value % modulus;
1778 std::string msg = toString(m_value) +
1779 " does not have a ModInverse using " +
1787 SignedNativeInt m0 = modulus;
1788 SignedNativeInt y = 0;
1789 SignedNativeInt x = 1;
1792 SignedNativeInt q = a / modulus;
1794 SignedNativeInt t = modulus;
1795 modulus = a % modulus;
1807 return NativeInt(x);
1817 *
this = ModInverse(mod);
1871 if (this->m_value < a.m_value)
1873 else if (this->m_value > a.m_value)
1885 template <
typename OutputType = NativeInt>
1887 if (
sizeof(OutputType) <
sizeof(m_value))
1889 "Invalid integer conversion: sizeof(OutputIntType) < " 1890 "sizeof(InputIntType)");
1891 return static_cast<OutputType
>(m_value);
1908 if (bitString.length() > MaxBits()) {
1910 "Bit string is too long to fit in a bigintnat");
1913 for (
size_t i = 0; i < bitString.length(); i++) {
1914 int n = bitString[i] -
'0';
1915 if (n < 0 || n > 1) {
1917 "Bit string must contain only 0 or 1");
1958 usint DigitLen = ceil(log2(base));
1960 usint newIndex = 1 + (index - 1) * DigitLen;
1961 for (usint i = 1; i < base; i = i * 2) {
1962 digit += GetBitAtIndex(newIndex) * i;
1979 return (m_value >> (index - 1)) & 0x01;
1996 const std::string
ToString()
const {
return toString(m_value); }
1998 static const std::string IntegerTypeName() {
return "UBNATINT"; }
2015 template <
class Archive,
typename T =
void>
2016 typename std::enable_if<std::is_same<NativeInt, U64BITS>::value ||
2017 std::is_same<NativeInt, U32BITS>::value,
2019 load(Archive &ar, std::uint32_t
const version) {
2020 if (version > SerializedVersion()) {
2022 "serialized object version " + std::to_string(version) +
2023 " is from a later version of the library");
2025 ar(::cereal::make_nvp(
"v", m_value));
2028 #if defined(HAVE_INT128) 2029 template <
class Archive>
2030 typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
2031 !cereal::traits::is_text_archive<Archive>::value,
2033 load(Archive &ar, std::uint32_t
const version) {
2034 if (version > SerializedVersion()) {
2036 "serialized object version " + std::to_string(version) +
2037 " is from a later version of the library");
2041 ar(::cereal::binary_data(vec,
sizeof(vec)));
2047 template <
class Archive>
2048 typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
2049 cereal::traits::is_text_archive<Archive>::value,
2051 load(Archive &ar, std::uint32_t
const version) {
2052 if (version > SerializedVersion()) {
2054 "serialized object version " + std::to_string(version) +
2055 " is from a later version of the library");
2059 ar(::cereal::make_nvp(
"i", vec));
2066 template <
class Archive,
typename T =
void>
2067 typename std::enable_if<std::is_same<NativeInt, U64BITS>::value ||
2068 std::is_same<NativeInt, U32BITS>::value,
2070 save(Archive &ar, std::uint32_t
const version)
const {
2071 ar(::cereal::make_nvp(
"v", m_value));
2074 #if defined(HAVE_INT128) 2075 template <
class Archive>
2076 typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
2077 !cereal::traits::is_text_archive<Archive>::value,
2079 save(Archive &ar, std::uint32_t
const version)
const {
2081 constexpr U128BITS mask = (
static_cast<U128BITS
>(1) << 64) - 1;
2083 vec[0] = m_value & mask;
2084 vec[1] = m_value >> 64;
2085 ar(::cereal::binary_data(vec,
sizeof(vec)));
2088 template <
class Archive>
2089 typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
2090 cereal::traits::is_text_archive<Archive>::value,
2092 save(Archive &ar, std::uint32_t
const version)
const {
2094 constexpr U128BITS mask = (
static_cast<U128BITS
>(1) << 64) - 1;
2096 vec[0] = m_value & mask;
2097 vec[1] = m_value >> 64;
2098 ar(::cereal::make_nvp(
"i", vec));
2102 std::string SerializedObjectName()
const {
return "NATInteger"; }
2104 static uint32_t SerializedVersion() {
return 1; }
2106 static constexpr
unsigned MaxBits() {
return m_uintBitLength; }
2108 static bool IsNativeInt() {
return true; }
2118 NativeInt test_value = 0;
2120 for (
size_t i = 0; i < str.length(); i++) {
2121 int v = str[i] -
'0';
2122 if (v < 0 || v > 9) {
2128 if (m_value < test_value) {
2131 str +
" is too large to fit in this native integer object");
2133 test_value = m_value;
2142 static constexpr
unsigned m_uintBitLength =
sizeof(NativeInt) * 8;
2144 static constexpr NativeInt m_uintMax = std::numeric_limits<NativeInt>::max();
2146 static constexpr NativeInt NATIVEINTMASK = NativeInt(~0);
2155 NativeInt newv = m_value + b.m_value;
2156 if (newv < m_value || newv < b.m_value) {
2169 return m_value + b.m_value;
2173 static inline void SubtractD(
typeD &res,
const typeD &a) {
2174 if (res.lo < a.lo) {
2175 res.lo += m_uintMax + 1 - a.lo;
2192 static inline NativeInt RShiftD(
const typeD &x,
long shift) {
2193 return (x.lo >> shift) | (x.hi << (MaxBits() - shift));
2205 static inline void MultD(U64BITS a, U64BITS b,
typeD &res) {
2206 #if defined(__x86_64__) 2209 : [ lo ]
"=a"(res.lo), [ hi ]
"=d"(res.hi)
2210 : [ a ]
"%[lo]"(a), [ b ]
"rm"(b)
2213 #elif defined(__aarch64__) 2219 asm(
"umulh %0, %1, %2\n\t" :
"=r"(res.hi) :
"r"(x.lo),
"r"(y));
2221 #elif defined(__arm__) // 32 bit processor 2222 uint64_t wres(0), wa(a), wb(b);
2225 res.hi = wres >> 32;
2226 res.lo = (uint32_t)wres & 0xFFFFFFFF;
2228 U128BITS wres(0), wa(a), wb(b);
2230 res.hi = (uint64_t)(wres >> 64);
2231 res.lo = (uint64_t)wres;
2232 #elif defined(__EMSCRIPTEN__) // web assembly 2233 U64BITS a1 = a >> 32;
2234 U64BITS a2 = (uint32_t)a;
2235 U64BITS b1 = b >> 32;
2236 U64BITS b2 = (uint32_t)b;
2241 U64BITS lowBefore = res.lo;
2243 U64BITS p1 = a2 * b1;
2244 U64BITS p2 = a1 * b2;
2245 U64BITS temp = p1 + p2;
2246 res.hi += temp >> 32;
2247 res.lo += U64BITS((uint32_t)temp) << 32;
2250 if (lowBefore > res.lo) res.hi++;
2253 if ((temp < p1) || (temp < p2)) res.hi += (U64BITS)1 << 32;
2255 #error Architecture not supported for MultD() 2259 #if defined(HAVE_INT128) 2260 static inline void MultD(U128BITS a, U128BITS b,
typeD &res) {
2264 U128BITS a1 = a >> 64;
2265 U128BITS a2 = (uint64_t)a;
2266 U128BITS b1 = b >> 64;
2267 U128BITS b2 = (uint64_t)b;
2272 U128BITS lowBefore = res.lo;
2274 U128BITS p1 = a2 * b1;
2275 U128BITS p2 = a1 * b2;
2276 U128BITS temp = p1 + p2;
2277 res.hi += temp >> 64;
2278 res.lo += U128BITS((uint64_t)temp) << 64;
2281 if (lowBefore > res.lo) res.hi++;
2284 if ((temp < p1) || (temp < p2)) res.hi += (U128BITS)1 << 64;
2288 static inline void MultD(U32BITS a, U32BITS b,
typeD &res) {
2289 DNativeInt prod = DNativeInt(a) * DNativeInt(b);
2290 res.hi = (prod >> MaxBits()) & NATIVEINTMASK;
2291 res.lo = prod & NATIVEINTMASK;
2302 static inline NativeInt MultDHi(NativeInt a, NativeInt b) {
2315 inline DNativeInt GetD(
const typeD &x)
const {
2316 return (DNativeInt(x.hi) << MaxBits()) | x.lo;
2319 static inline std::string toString(uint32_t value) {
2320 return std::to_string(value);
2323 static inline std::string toString(uint64_t value) {
2324 return std::to_string(value);
2327 #if defined(HAVE_INT128) 2328 static inline std::string toString(
unsigned __int128 value) {
2329 constexpr uint32_t maxChars = 15;
2332 const uint64_t divisor = std::llrint(pow(10, maxChars));
2333 uint64_t part3 = value % divisor;
2335 uint64_t part2 = value % divisor;
2337 uint64_t part1 = value % divisor;
2344 bool appendNextPart =
false;
2346 ret = std::to_string(part1);
2347 appendNextPart =
true;
2351 std::string part2str(std::to_string(part2));
2352 if (appendNextPart) {
2353 ret += std::string(maxChars - part2str.size(),
'0');
2357 appendNextPart =
true;
2359 }
else if (appendNextPart) {
2360 ret += std::string(maxChars,
'0');
2364 std::string part3str(std::to_string(part3));
2365 if (appendNextPart) {
2366 ret += std::string(maxChars - part3str.size(),
'0');
2371 }
else if (appendNextPart) {
2372 ret += std::string(maxChars,
'0');
2402 #endif // LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H const double LOG2_10
A pre-computed constant of Log base 2 of 10.
Definition: ubintnat.h:71
const NativeIntegerT & operator=(const NativeIntegerT &val)
ASSIGNMENT OPERATORS.
Definition: ubintnat.h:277
static NativeIntegerT Allocator()
Definition: ubintnat.h:1986
const NativeIntegerT & MulEq(const NativeIntegerT &b)
Definition: ubintnat.h:496
NativeIntegerT Sub(const NativeIntegerT &b) const
Definition: ubintnat.h:395
NativeIntegerT ModSub(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu) const
Definition: ubintnat.h:1139
NativeIntegerT SubCheck(const NativeIntegerT &b) const
Definition: ubintnat.h:405
Definition: ubintnat.h:136
const NativeIntegerT & ModSubEq(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu)
Definition: ubintnat.h:1167
const NativeIntegerT & ModAddEq(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu)
Definition: ubintnat.h:1018
NativeIntegerT Mul(const NativeIntegerT &b) const
Definition: ubintnat.h:463
const NativeIntegerT & LShiftEq(usshort shift)
Definition: ubintnat.h:1837
const NativeIntegerT & SubEqFast(const NativeIntegerT &b)
Definition: ubintnat.h:448
const NativeIntegerT & ModSubFastEq(const NativeIntegerT &b, const NativeIntegerT &modulus)
Definition: ubintnat.h:1121
const NativeIntegerT & DividedByEq(const NativeIntegerT &b)
Definition: ubintnat.h:545
NativeIntegerT Mod(const NativeIntegerT &modulus, const NativeIntegerT &mu, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:772
const NativeIntegerT & AddEqCheck(const NativeIntegerT &b)
Definition: ubintnat.h:368
const NativeIntegerT & SubEqCheck(const NativeIntegerT &b)
Definition: ubintnat.h:436
usint GetMSB() const
Definition: ubintnat.h:1932
const NativeIntegerT & ModAddEq(const NativeIntegerT &b, const NativeIntegerT &modulus)
Definition: ubintnat.h:936
const NativeIntegerT & MultiplyAndRoundEq(const NativeIntegerT &p, const NativeIntegerT &q)
Definition: ubintnat.h:618
NativeIntegerT(const NativeIntegerT &&val)
Definition: ubintnat.h:168
const NativeIntegerT & ModSubEq(const NativeIntegerT &b, const NativeIntegerT &modulus)
Definition: ubintnat.h:1072
Definition: stl_allocator.h:124
Definition: exception.h:133
NativeIntegerT MultiplyAndDivideQuotient(const NativeIntegerT &p, const NativeIntegerT &q, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:634
const std::string ToString() const
Definition: ubintnat.h:1996
NativeIntegerT Mod(const NativeIntegerT &modulus) const
Definition: ubintnat.h:724
NativeIntegerT ModExp(const NativeIntegerT &b, const NativeIntegerT &mod, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:1689
NativeIntegerT Add(const NativeIntegerT &b) const
Definition: ubintnat.h:347
const NativeIntegerT & MulEqCheck(const NativeIntegerT &b)
Definition: ubintnat.h:507
NativeIntegerT MulFast(const NativeIntegerT &b) const
Definition: ubintnat.h:486
NativeIntegerT LShift(usshort shift) const
Definition: ubintnat.h:1829
uschar GetBitAtIndex(usint index) const
Definition: ubintnat.h:1974
const NativeIntegerT & SubEq(const NativeIntegerT &b)
Definition: ubintnat.h:425
void SetValue(const NativeIntegerT &val)
Definition: ubintnat.h:331
Definition: exception.h:147
NativeIntegerT ModMul(const NativeIntegerT &b, const NativeIntegerT &modulus, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:1195
NativeIntegerT DivideAndRound(const NativeIntegerT &q) const
Definition: ubintnat.h:692
Definition: exception.h:113
const NativeIntegerT & ModMulFastEq(const NativeIntegerT &b, const NativeIntegerT &modulus)
Definition: ubintnat.h:1435
NativeIntegerT ModSub(const NativeIntegerT &b, const NativeIntegerT &modulus) const
Definition: ubintnat.h:1043
NativeIntegerT ModAdd(const NativeIntegerT &b, const NativeIntegerT &modulus) const
Definition: ubintnat.h:911
NativeIntegerT(int16_t init, typename std::enable_if<!std::is_same< T, int16_t >::value, bool >::type=true)
Definition: ubintnat.h:190
NativeIntegerT ModInverse(const NativeIntegerT &mod) const
Definition: ubintnat.h:1774
const NativeIntegerT & AddEq(const NativeIntegerT &b)
Definition: ubintnat.h:357
usint GetLengthForBase(usint base) const
Definition: ubintnat.h:1941
const NativeIntegerT & operator=(const std::string strval)
Definition: ubintnat.h:299
NativeIntegerT PrepModMulConst(const NativeIntegerT &modulus, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:1624
NativeIntegerT Exp(usint p) const
Definition: ubintnat.h:557
const NativeIntegerT & MulEqFast(const NativeIntegerT &b)
Definition: ubintnat.h:523
NativeIntegerT SubFast(const NativeIntegerT &b) const
Definition: ubintnat.h:415
const NativeIntegerT & ModMulFastConstEq(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &bInv)
Definition: ubintnat.h:1669
NativeIntegerT ModAddFast(const NativeIntegerT &b, const NativeIntegerT &modulus) const
Definition: ubintnat.h:960
const NativeIntegerT & ModMulFastEq(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true)
Definition: ubintnat.h:1544
const NativeIntegerT & ExpEq(usint p)
Definition: ubintnat.h:578
int Compare(const NativeIntegerT &a) const
Definition: ubintnat.h:1870
Main class for big integers represented as an array of native (primitive) unsigned integers...
Definition: ubintfxd.h:219
const usint BARRETT_LEVELS
The number of levels (precomputed values) used in the Barrett reductions.
Definition: ubintnat.h:74
NativeIntegerT ModSubFast(const NativeIntegerT &b, const NativeIntegerT &modulus) const
Definition: ubintnat.h:1100
const NativeIntegerT & ModInverseEq(const NativeIntegerT &mod)
Definition: ubintnat.h:1816
const NativeIntegerT & ModAddFastEq(const NativeIntegerT &b, const NativeIntegerT &modulus)
Definition: ubintnat.h:975
const NativeIntegerT & ModMulEq(const NativeIntegerT &b, const NativeIntegerT &modulus, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true)
Definition: ubintnat.h:1243
NativeIntegerT ComputeMu(typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:745
const NativeIntegerT & DivideAndRoundEq(const NativeIntegerT &q)
Definition: ubintnat.h:712
usint GetDigitAtIndexForBase(usint index, usint base) const
Definition: ubintnat.h:1957
NativeIntegerT ModAdd(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu) const
Definition: ubintnat.h:992
const NativeIntegerT & ModExpEq(const NativeIntegerT &b, const NativeIntegerT &mod)
Definition: ubintnat.h:1762
NativeIntegerT(const lbcrypto::BigInteger &val)
Definition: ubintnat.h:258
NativeIntegerT RShift(usshort shift) const
Definition: ubintnat.h:1848
NativeIntegerT(NativeInt val)
Definition: ubintnat.h:183
const NativeIntegerT & RShiftEq(usshort shift)
Definition: ubintnat.h:1856
void SetValue(const std::string &strval)
Definition: ubintnat.h:323
OutputType ConvertToInt() const
Definition: ubintnat.h:1886
NativeIntegerT ModMulFast(const NativeIntegerT &b, const NativeIntegerT &modulus, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:1396
const NativeIntegerT & operator=(const NativeInt &val)
Definition: ubintnat.h:310
NativeIntegerT(const NativeIntegerT &val)
Definition: ubintnat.h:161
const NativeIntegerT & ModMulEq(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true)
Definition: ubintnat.h:1307
Struct to determine a datatype that is twice as big(bitwise) as utype. sets T as of type void for def...
Definition: ubintnat.h:84
const NativeIntegerT & ModEq(const NativeIntegerT &modulus, const NativeIntegerT &mu, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true)
Definition: ubintnat.h:843
friend std::ostream & operator<<(std::ostream &os, const NativeIntegerT &ptr_obj)
Definition: ubintnat.h:2007
NativeIntegerT(const std::string &strval)
Definition: ubintnat.h:176
const NativeIntegerT & AddEqFast(const NativeIntegerT &b)
Definition: ubintnat.h:384
const NativeIntegerT & ModEq(const NativeIntegerT &modulus)
Definition: ubintnat.h:734
void AssignVal(const std::string &str)
Definition: ubintnat.h:2117
Definition: interface.h:33
void SetIdentity()
Definition: ubintnat.h:337
usint GetMSB(IntType x)
Definition: nbtheory.h:171
NativeIntegerT MultiplyAndRound(const NativeIntegerT &p, const NativeIntegerT &q) const
Definition: ubintnat.h:604
Main class for big integers represented as an array of native (primitive) unsigned integers...
Definition: backend.h:60
NativeIntegerT ModMulFast(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:1466
NativeIntegerT MulCheck(const NativeIntegerT &b) const
Definition: ubintnat.h:473
const NativeIntegerT & operator=(const NativeIntegerT &&val)
Definition: ubintnat.h:288
static NativeIntegerT FromBinaryString(const std::string &bitString)
Definition: ubintnat.h:1907
NativeIntegerT()
CONSTRUCTORS.
Definition: ubintnat.h:154
NativeIntegerT ModMulFastConst(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &bInv) const
Definition: ubintnat.h:1650
NativeIntegerT ModMul(const NativeIntegerT &b, const NativeIntegerT &modulus, const NativeIntegerT &mu) const
Definition: ubintnat.h:1291
NativeIntegerT DividedBy(const NativeIntegerT &b) const
Definition: ubintnat.h:534
double ConvertToDouble() const
Definition: ubintnat.h:1899
NativeIntegerT MultiplyAndDivideRemainder(const NativeIntegerT &p, const NativeIntegerT &q, typename std::enable_if<!std::is_same< T, DNativeInt >::value, bool >::type=true) const
Definition: ubintnat.h:664