diff --git a/include/CppCore.Interface.C/cppcore.h b/include/CppCore.Interface.C/cppcore.h
index 21c70e40..ea5cb7e8 100644
--- a/include/CppCore.Interface.C/cppcore.h
+++ b/include/CppCore.Interface.C/cppcore.h
@@ -13,17 +13,18 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// macro for large integer arithmetic function declarations
-#define CPPCORE_UINT_DECLARATION(name) \
- CPPCORE_EXPORT void name ## _shl (void* a, unsigned int b, void* r); \
- CPPCORE_EXPORT void name ## _shr (void* a, unsigned int b, void* r); \
- CPPCORE_EXPORT void name ## _add (void* a, void* b, void* r); \
- CPPCORE_EXPORT void name ## _sub (void* a, void* b, void* r); \
- CPPCORE_EXPORT void name ## _mul (void* a, void* b, void* r); \
- CPPCORE_EXPORT void name ## _square(void* a, void* r); \
- CPPCORE_EXPORT void name ## _divmod(void* a, void* b, void* q, void* r); \
- CPPCORE_EXPORT void name ## _mulmod(void* a, void* b, void* m, void* r); \
- CPPCORE_EXPORT void name ## _powmod(void* a, void* b, void* m, void* r); \
- CPPCORE_EXPORT void name ## _gcd (void* a, void* b, void* r);
+#define CPPCORE_UINT_DECLARATION(name) \
+ CPPCORE_EXPORT void name ## _shl (void* a, unsigned int b, void* r); \
+ CPPCORE_EXPORT void name ## _shr (void* a, unsigned int b, void* r); \
+ CPPCORE_EXPORT void name ## _add (void* a, void* b, void* r); \
+ CPPCORE_EXPORT void name ## _sub (void* a, void* b, void* r); \
+ CPPCORE_EXPORT void name ## _mul (void* a, void* b, void* r); \
+ CPPCORE_EXPORT void name ## _square (void* a, void* r); \
+ CPPCORE_EXPORT void name ## _divmod (void* a, void* b, void* q, void* r); \
+ CPPCORE_EXPORT void name ## _mulmod (void* a, void* b, void* m, void* r); \
+ CPPCORE_EXPORT void name ## _squaremod(void* a, void* m, void* r); \
+ CPPCORE_EXPORT void name ## _powmod (void* a, void* b, void* m, void* r); \
+ CPPCORE_EXPORT void name ## _gcd (void* a, void* b, void* r);
// macro for basex function declarations
#define CPPCORE_BASEX_DECLARATION(size) \
diff --git a/include/CppCore.Test/Math/Util.h b/include/CppCore.Test/Math/Util.h
index 27263de3..6b972954 100644
--- a/include/CppCore.Test/Math/Util.h
+++ b/include/CppCore.Test/Math/Util.h
@@ -493,16 +493,41 @@ namespace CppCore { namespace Test { namespace Math
INLINE static bool usquare()
{
- uint64_t a[4] = { 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL };
- uint64_t r1[9] = { 0x0000000000000001ULL,0x0000000000000000ULL,0x0000000000000000ULL,0x0000000000000000ULL,
+ uint64_t a1[4] = { 0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL };
+ uint64_t r1_1[9] = { 0x0000000000000001ULL,0x0000000000000000ULL,0x0000000000000000ULL,0x0000000000000000ULL,
0xFFFFFFFFFFFFFFFEULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,0xFFFFFFFFFFFFFFFFULL,
0x0000000000000000ULL };
- uint64_t r2[9];
- CppCore::usquare(a, r2);
- if (!CppCore::equal(r1, r2))
+ uint64_t r1_2[9];
+ CppCore::usquare(a1, r1_2);
+ if (!CppCore::equal(r1_1, r1_2))
+ return false;
+
+ uint64_t a2 = 2;
+ uint64_t r2_1[2] = { 0x000000000004ULL, 0x0000000000000000ULL };
+ uint64_t r2_2[2];
+ CppCore::usquare(a2, r2_2);
+ if (!CppCore::equal(r2_1, r2_2))
+ return false;
+
+ uint64_t a3[2] = { 0x000000000002ULL, 0x0000000000000000ULL };
+ uint64_t r3_1 = 0x000000000004ULL;
+ uint64_t r3_2;
+ CppCore::usquare(a3, r3_2);
+ if (!CppCore::equal(r3_1, r3_2))
+ return false;
+
+ uint64_t a4 = 2;
+ uint64_t r4_1 = 4;
+ uint64_t r4_2;
+ CppCore::usquare(a4, r4_2);
+ if (!CppCore::equal(r4_1, r4_2))
return false;
return
+ usquare_template<1, 1>() &&
+ usquare_template<1, 2>() &&
+ usquare_template<1, 3>() &&
+ usquare_template<2, 1>() &&
usquare_template<4, 2>() &&
usquare_template<4, 4>() &&
usquare_template<4, 8>() &&
diff --git a/include/CppCore/Math/Primes.h b/include/CppCore/Math/Primes.h
index 98df104c..5f54cf3b 100644
--- a/include/CppCore/Math/Primes.h
+++ b/include/CppCore/Math/Primes.h
@@ -130,8 +130,7 @@ namespace CppCore
return true;
for (uint32_t i = 1U; i < s; i++)
{
- //TODO: usquaremod
- CppCore::umulmod(r, r, n, r, m);
+ CppCore::usquaremod(r, n, r, m);
if (r <= 1U) return false;
if (r == t) return true;
}
@@ -314,7 +313,7 @@ namespace CppCore
UINTX2 mem[2];
for (uint32_t i = 2U; i < ith; i++)
{
- CppCore::umul(s, s, r);
+ CppCore::usquare(s, r);
CppCore::usub(r, (size_t)2U, r);
CppCore::umod(s, r, n, mem);
}
@@ -418,7 +417,7 @@ namespace CppCore
// perfect square root test
CppCore::isqrt(n, t);
- CppCore::umul(t, t, d);
+ CppCore::usquare(t, d);
if (CppCore::equal(n, d))
return Primes::NotPrime;
diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h
index 56dc8eb2..553a3da1 100644
--- a/include/CppCore/Math/Util.h
+++ b/include/CppCore/Math/Util.h
@@ -2951,7 +2951,10 @@ namespace CppCore
rp[i] = 0ULL;
// calculate one triangle
rp[0] = 0ULL;
- CppCore::umul128(ap[0], ap[1], rp[1], k);
+ if (NA > 1 && NR > 1)
+ CppCore::umul128(ap[0], ap[1], rp[1], k);
+ else
+ k = 0ULL;
for (size_t j = 2; j < MIN(NA,NR); j++)
{
CppCore::umul128(ap[0], ap[j], tl, th);
@@ -3006,7 +3009,10 @@ namespace CppCore
rp[i] = 0U;
// calculate one triangle
rp[0] = 0U;
- CppCore::umul64(ap[0], ap[1], rp[1], k);
+ if (NA > 1 && NR > 1)
+ CppCore::umul64(ap[0], ap[1], rp[1], k);
+ else
+ k = 0U;
for (size_t j = 2; j < MIN(NA,NR); j++)
{
CppCore::umul64(ap[0], ap[j], tl, th);
@@ -3980,6 +3986,87 @@ namespace CppCore
}
#endif
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // SQUAREMOD
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ ///
+ /// a*a mod m. For any sized integers that are multiples of 32-bit.
+ ///
+ template
+ INLINE static void usquaremod(const UINT& a, const UINT& m, UINT& r, UINT p[3])
+ {
+ struct UINTX2 { UINT x[2]; };
+ CppCore::usquare(a, *(UINTX2*)p);
+ CppCore::umod(r, *(UINTX2*)p, m, (UINTX2*)p);
+ }
+
+ ///
+ /// a*a mod m. For any sized integers that are multiples of 32-bit.
+ ///
+ template
+ INLINE static void usquaremod(const UINT& a, const UINT& m, UINT& r)
+ {
+ CPPCORE_ALIGN_OPTIM(UINT) p[3];
+ CppCore::usquaremod(a, m, r, p);
+ }
+
+ ///
+ /// Template Specialization for 16-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint16_t& a, const uint16_t& m, uint16_t& r, uint16_t p[3])
+ {
+ CppCore::umulmod16(a, a, m, r);
+ }
+
+ ///
+ /// Template Specialization for 16-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint16_t& a, const uint16_t& m, uint16_t& r)
+ {
+ CppCore::umulmod16(a, a, m, r);
+ }
+
+ ///
+ /// Template Specialization for 32-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint32_t& a, const uint32_t& m, uint32_t& r, uint32_t p[3])
+ {
+ CppCore::umulmod32(a, a, m, r);
+ }
+
+ ///
+ /// Template Specialization for 32-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint32_t& a, const uint32_t& m, uint32_t& r)
+ {
+ CppCore::umulmod32(a, a, m, r);
+ }
+
+ ///
+ /// Template Specialization for 64-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint64_t& a, const uint64_t& m, uint64_t& r, uint64_t p[3])
+ {
+ #if defined(CPPCORE_CPU_X64)
+ CppCore::umulmod64(a, a, m, r);
+ #else
+ CppCore::umulmod(a, a, m, r);
+ #endif
+ }
+
+ ///
+ /// Template Specialization for 64-Bit Unsigned.
+ ///
+ template<> INLINE void usquaremod(const uint64_t& a, const uint64_t& m, uint64_t& r)
+ {
+ #if defined(CPPCORE_CPU_X64)
+ CppCore::umulmod64(a, a, m, r);
+ #else
+ CppCore::umulmod(a, a, m, r);
+ #endif
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// POWMOD
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -4006,7 +4093,7 @@ namespace CppCore
{
if (CppCore::bittest(b, i))
CppCore::umulmod(r, a, m, r, t);
- CppCore::umulmod(a, a, m, a, t); //TODO: usquaremod
+ CppCore::usquaremod(a, m, a, t);
}
}
@@ -4053,10 +4140,9 @@ namespace CppCore
// Process k bits at a time from left to right (MSB to LSB)
for (int pos = HIDX_K - K; pos >= 0; pos -= K) {
-
if (pos < HIDX_K - K)
for (size_t i = 0; i < K; i++)
- CppCore::umulmod(r, r, m, r, t);
+ CppCore::usquaremod(r, m, r, t);
const uint32_t N = MIN(K, NUMBITS-pos);
const uint32_t CHUNK = CppCore::getbits32(b, pos, N);
CppCore::umulmod(r, powers[CHUNK], m, r, t);
diff --git a/src/CppCore.Interface.C/cppcore.cpp b/src/CppCore.Interface.C/cppcore.cpp
index 85fabab0..32998c12 100644
--- a/src/CppCore.Interface.C/cppcore.cpp
+++ b/src/CppCore.Interface.C/cppcore.cpp
@@ -57,17 +57,18 @@ void cppcore_free (void* ptr) { CPPCORE_ALIGNED_FREE(ptr); }
#include
#include
-#define CPPCORE_UINT_IMPLEMENTATION(name, cname) \
- void name ## _shl (void* a, unsigned int b, void* r) { CppCore::shl(*(cname*)r, *(cname*)a, b);} \
- void name ## _shr (void* a, unsigned int b, void* r) { CppCore::shr(*(cname*)r, *(cname*)a, b);} \
- void name ## _add (void* a, void* b, void* r) { CppCore::uadd(*(cname*)a, *(cname*)b, *(cname*)r);} \
- void name ## _sub (void* a, void* b, void* r) { CppCore::usub(*(cname*)a, *(cname*)b, *(cname*)r);} \
- void name ## _mul (void* a, void* b, void* r) { CppCore::umul(*(cname*)a, *(cname*)b, *(cname*)r);} \
- void name ## _square(void* a, void* r) { CppCore::usquare(*(cname*)a, *(cname*)r);} \
- void name ## _divmod(void* a, void* b, void* q, void* r){ CppCore::udivmod(*(cname*)q,*(cname*)r,*(cname*)a,*(cname*)b);}\
- void name ## _mulmod(void* a, void* b, void* m, void* r){ CppCore::umulmod(*(cname*)a,*(cname*)b,*(cname*)m,*(cname*)r);}\
- void name ## _powmod(void* a, void* b, void* m, void* r){ CppCore::upowmod(*(cname*)a,*(cname*)b,*(cname*)m,*(cname*)r);}\
- void name ## _gcd (void* a, void* b, void* r) { CppCore::gcd(*(cname*)a, *(cname*)b, *(cname*)r);}
+#define CPPCORE_UINT_IMPLEMENTATION(name, cname) \
+ void name ## _shl (void* a, unsigned int b, void* r) { CppCore::shl(*(cname*)r, *(cname*)a, b);} \
+ void name ## _shr (void* a, unsigned int b, void* r) { CppCore::shr(*(cname*)r, *(cname*)a, b);} \
+ void name ## _add (void* a, void* b, void* r) { CppCore::uadd(*(cname*)a, *(cname*)b, *(cname*)r);} \
+ void name ## _sub (void* a, void* b, void* r) { CppCore::usub(*(cname*)a, *(cname*)b, *(cname*)r);} \
+ void name ## _mul (void* a, void* b, void* r) { CppCore::umul(*(cname*)a, *(cname*)b, *(cname*)r);} \
+ void name ## _square (void* a, void* r) { CppCore::usquare(*(cname*)a, *(cname*)r);} \
+ void name ## _divmod (void* a, void* b, void* q, void* r){ CppCore::udivmod(*(cname*)q,*(cname*)r,*(cname*)a,*(cname*)b);}\
+ void name ## _mulmod (void* a, void* b, void* m, void* r){ CppCore::umulmod(*(cname*)a,*(cname*)b,*(cname*)m,*(cname*)r);}\
+ void name ## _squaremod(void* a, void* m, void* r) { CppCore::usquaremod(*(cname*)a,*(cname*)m,*(cname*)r);} \
+ void name ## _powmod (void* a, void* b, void* m, void* r){ CppCore::upowmod(*(cname*)a,*(cname*)b,*(cname*)m,*(cname*)r);}\
+ void name ## _gcd (void* a, void* b, void* r) { CppCore::gcd(*(cname*)a, *(cname*)b, *(cname*)r);}
CPPCORE_UINT_IMPLEMENTATION(cppcore_uint32, std::uint32_t)
CPPCORE_UINT_IMPLEMENTATION(cppcore_uint64, std::uint64_t)