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)