From 49ba8e426735f01fdc7517b1387bd5107116ff86 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Thu, 30 Jul 2026 20:16:27 +0200 Subject: [PATCH 1/6] wip --- include/CppCore/Math/Util.h | 58 +++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index 2294354a..619bcf9d 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3538,9 +3538,10 @@ namespace CppCore else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) % 8 == 0) { // using 64-bit chunks - assert(&r != &v); + assert((void*)&r != (void*)&v); + assert((void*)&r != (void*)&u); static_assert(sizeof(MEM) >= sizeof(UINT1) + 8U); - static_assert(sizeof(UINT1) >= sizeof(UINT2)); + static_assert(sizeof(MEM) >= sizeof(UINT2)); static_assert(alignof(MEM) >= alignof(UINT1)); static_assert(alignof(MEM) >= alignof(UINT2)); constexpr uint32_t M = sizeof(UINT1) / 8; @@ -3552,23 +3553,30 @@ namespace CppCore uint64_t* vno; uint64_t* vne; uint32_t n = N; + uint32_t m = M; + CppCore::clear(r); while (n != 0U && vp[n-1] == 0U) n--; if (n == 0U) return; + while (m != 0U && up[m-1] == 0U) + m--; + if (n > m) { + if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&u); + else CppCore::clone(*(UINT1*)&r, u); + return; + } if (n == 1U) { - CppCore::clear(r); - *rp = CppCore::umod128_64x(up, *vp, M); + *rp = CppCore::umod128_64x(up, *vp, m); return; } const auto S((uint8_t)CppCore::lzcnt(vp[n-1])); if (S) { - CppCore::clear(r); CppCore::shl64x(vp, rp, n, S); vno = rp; vne = &rp[n]; - unp[M] = up[M-1] >> (64U-S); - CppCore::shl64x(up, unp, M, S); + unp[m] = up[m-1] >> (64U-S); + CppCore::shl64x(up, unp, m, S); } else { vno = vp; @@ -3578,7 +3586,7 @@ namespace CppCore } const auto VNN1 = vno[n-1]; const auto VNN2 = vno[n-2]; - for (uint32_t j = M-n; j != UINT32_MAX; j--) + for (uint32_t j = m-n; j != UINT32_MAX; j--) { auto* unpjo = &unp[j]; auto* unpj = unpjo; @@ -3632,15 +3640,19 @@ namespace CppCore *unpj = kl; } if (S) { CppCore::shr64x(unp, rp, n, S); } - else { CppCore::clone(r, *(UINT2*)&mem); } + else { + if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&mem); + else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); + } } else #endif { // using 32-bit chunks - assert(&r != &v); + assert((void*)&r != (void*)&v); + assert((void*)&r != (void*)&u); static_assert(sizeof(MEM) >= sizeof(UINT1) + 4U); - static_assert(sizeof(UINT1) >= sizeof(UINT2)); + static_assert(sizeof(MEM) >= sizeof(UINT2)); static_assert(alignof(MEM) >= alignof(UINT1)); static_assert(alignof(MEM) >= alignof(UINT2)); constexpr uint32_t M = sizeof(UINT1) / 4; @@ -3652,23 +3664,30 @@ namespace CppCore uint32_t* vno; uint32_t* vne; uint32_t n = N; + uint32_t m = M; + CppCore::clear(r); while (n != 0U && vp[n-1] == 0U) n--; if (n == 0U) return; + while (m != 0U && up[m-1] == 0U) + m--; + if (n > m) { + if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&u); + else CppCore::clone(*(UINT1*)&r, u); + return; + } if (n == 1U) { - CppCore::clear(r); - *rp = CppCore::umod64_32x(up, *vp, M); + *rp = CppCore::umod64_32x(up, *vp, m); return; } const auto S((uint8_t)CppCore::lzcnt(vp[n-1])); if (S) { - CppCore::clear(r); CppCore::shl32x(vp, rp, n, S); vno = rp; vne = &rp[n]; - unp[M] = up[M-1] >> (32U-S); - CppCore::shl32x(up, unp, M, S); + unp[m] = up[m-1] >> (32U-S); + CppCore::shl32x(up, unp, m, S); } else { vno = vp; @@ -3678,7 +3697,7 @@ namespace CppCore } const auto VNN1 = vno[n-1]; const auto VNN2 = vno[n-2]; - for (uint32_t j = M-n; j != UINT32_MAX; j--) + for (uint32_t j = m-n; j != UINT32_MAX; j--) { auto* unpjo = &unp[j]; auto* unpj = unpjo; @@ -3732,7 +3751,10 @@ namespace CppCore *unpj = kl; } if (S) { CppCore::shr32x(unp, rp, n, S); } - else { CppCore::clone(r, *(UINT2*)&mem); } + else { + if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&mem); + else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); + } } } From fda34074fd209d8d16e12db226f1aa265d61e871 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Fri, 31 Jul 2026 17:04:32 +0200 Subject: [PATCH 2/6] wip --- include/CppCore/Math/Util.h | 54 ++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index 619bcf9d..c239487d 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3496,19 +3496,23 @@ namespace CppCore /// Modulo for any sized unsigned integers. /// Based on Knuth's Algorithm in Hacker's Delight. (r=u%v) /// - template - INLINE static void umod(UINT2& r, const UINT1& u, const UINT2& v, MEM& mem) + template + INLINE static void umod(UINT3& r, const UINT1& u, const UINT2& v, MEM& mem) { - static_assert(sizeof(UINT1) != 0 && sizeof(UINT2) != 0 && sizeof(MEM) != 0); + static_assert(sizeof(UINT1) != 0 && sizeof(UINT2) != 0 && sizeof(UINT3) != 0 && sizeof(MEM) != 0); if constexpr (sizeof(UINT1) < sizeof(size_t)) { CppCore::umod(r, (size_t)u, v, mem); } else if constexpr (sizeof(UINT2) < sizeof(size_t)) + { + CppCore::umod(r, u, (size_t)v, mem); + } + else if constexpr (sizeof(UINT3) < sizeof(size_t)) { size_t tr; - CppCore::umod(tr, u, (size_t)v, mem); - CppCore::clone(r, *(UINT2*)&tr); + CppCore::umod(tr, u, v, mem); + CppCore::clone(r, *(UINT3*)&tr); } else if constexpr (sizeof(UINT1) % sizeof(size_t) != 0) { @@ -3518,8 +3522,12 @@ namespace CppCore else if constexpr (sizeof(UINT2) % sizeof(size_t) != 0) { Padded tv(v); - Padded tr; - CppCore::umod(tr, u, tv, mem); + CppCore::umod(r, u, tv, mem); + } + else if constexpr (sizeof(UINT3) % sizeof(size_t) != 0) + { + Padded tr; + CppCore::umod(tr, u, v, mem); CppCore::clone(r, tr.v); } #if defined(CPPCORE_CPU_X64) @@ -3540,10 +3548,11 @@ namespace CppCore // using 64-bit chunks assert((void*)&r != (void*)&v); assert((void*)&r != (void*)&u); + static_assert(sizeof(UINT3) >= MIN(sizeof(UINT1), sizeof(UINT2))); static_assert(sizeof(MEM) >= sizeof(UINT1) + 8U); - static_assert(sizeof(MEM) >= sizeof(UINT2)); static_assert(alignof(MEM) >= alignof(UINT1)); static_assert(alignof(MEM) >= alignof(UINT2)); + static_assert(alignof(MEM) >= alignof(UINT3)); constexpr uint32_t M = sizeof(UINT1) / 8; constexpr uint32_t N = sizeof(UINT2) / 8; uint64_t* rp = (uint64_t*)&r; @@ -3562,7 +3571,8 @@ namespace CppCore while (m != 0U && up[m-1] == 0U) m--; if (n > m) { - if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&u); + if constexpr (sizeof(UINT3) <= sizeof(UINT1)) + CppCore::clone(r, *(UINT3*)&u); else CppCore::clone(*(UINT1*)&r, u); return; } @@ -3641,7 +3651,8 @@ namespace CppCore } if (S) { CppCore::shr64x(unp, rp, n, S); } else { - if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&mem); + if constexpr (sizeof(UINT3) <= sizeof(UINT1)) + CppCore::clone(r, *(UINT3*)&mem); else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); } } @@ -3651,10 +3662,11 @@ namespace CppCore // using 32-bit chunks assert((void*)&r != (void*)&v); assert((void*)&r != (void*)&u); + static_assert(sizeof(UINT3) >= MIN(sizeof(UINT1), sizeof(UINT2))); static_assert(sizeof(MEM) >= sizeof(UINT1) + 4U); - static_assert(sizeof(MEM) >= sizeof(UINT2)); static_assert(alignof(MEM) >= alignof(UINT1)); static_assert(alignof(MEM) >= alignof(UINT2)); + static_assert(alignof(MEM) >= alignof(UINT3)); constexpr uint32_t M = sizeof(UINT1) / 4; constexpr uint32_t N = sizeof(UINT2) / 4; uint32_t* rp = (uint32_t*)&r; @@ -3673,7 +3685,8 @@ namespace CppCore while (m != 0U && up[m-1] == 0U) m--; if (n > m) { - if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&u); + if constexpr (sizeof(UINT3) <= sizeof(UINT1)) + CppCore::clone(r, *(UINT3*)&u); else CppCore::clone(*(UINT1*)&r, u); return; } @@ -3752,7 +3765,8 @@ namespace CppCore } if (S) { CppCore::shr32x(unp, rp, n, S); } else { - if constexpr (M >= N) CppCore::clone(r, *(UINT2*)&mem); + if constexpr (sizeof(UINT3) <= sizeof(UINT1)) + CppCore::clone(r, *(UINT3*)&mem); else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); } } @@ -3761,10 +3775,10 @@ namespace CppCore /// /// Like other variant but using temporary stack memory /// - template - INLINE static void umod(UINT2& r, const UINT1& u, const UINT2& v) + template + INLINE static void umod(UINT3& r, const UINT1& u, const UINT2& v) { - struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), alignof(UINT2)))) MEM { + struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), MAX(alignof(UINT2), alignof(UINT3))))) MEM { Padded x; size_t p; }; @@ -3796,6 +3810,14 @@ namespace CppCore r = u % v; } + /// + /// 64%32=64 + /// + template<> INLINE void umod(uint64_t& r, const uint64_t& u, const uint32_t& v) + { + r = u % v; + } + /// /// TODO: Special Version for High Bit on Divisor set. /// From b10d7835546c588bc6df420447dfe8b5ee12ffbf Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Fri, 31 Jul 2026 17:24:30 +0200 Subject: [PATCH 3/6] wip --- include/CppCore/Math/Util.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index c239487d..710b7bf2 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3974,8 +3974,8 @@ namespace CppCore /// /// a*b mod m. For any sized integers that are multiples of 32-bit. /// - template - INLINE static void umulmod(const UINT1& a, const UINT2& b, const UINT3& m, UINT3& r, MEM& mem) + template + INLINE static void umulmod(const UINT1& a, const UINT2& b, const UINT3& m, UINT4& r, MEM& mem) { static_assert(sizeof(MEM) >= sizeof(Padded) + sizeof(Padded) + sizeof(size_t)); struct UINTX2 { UINT1 a; UINT2 b; }; @@ -3986,10 +3986,10 @@ namespace CppCore /// /// a*b mod m. For any sized integers that are multiples of 32-bit. /// - template - INLINE static void umulmod(const UINT1& a, const UINT2& b, const UINT3& m, UINT3& r) + template + INLINE static void umulmod(const UINT1& a, const UINT2& b, const UINT3& m, UINT4& r) { - struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), MAX(alignof(UINT2), alignof(UINT3))))) MEM { + struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), MAX(alignof(UINT2), MAX(alignof(UINT3), alignof(UINT4)))))) MEM { Padded a; Padded b; size_t p; @@ -4064,8 +4064,8 @@ namespace CppCore /// /// a*a mod m. For any sized integers that are multiples of 32-bit. /// - template - INLINE static void usquaremod(const UINT1& a, const UINT2& m, UINT2& r, MEM& mem) + template + INLINE static void usquaremod(const UINT1& a, const UINT2& m, UINT3& r, MEM& mem) { static_assert(sizeof(MEM) >= sizeof(Padded) + sizeof(Padded) + sizeof(size_t)); struct UINTX2 { UINT1 a1; UINT1 a2; }; @@ -4076,10 +4076,10 @@ namespace CppCore /// /// a*a mod m. For any sized integers that are multiples of 32-bit. /// - template - INLINE static void usquaremod(const UINT1& a, const UINT2& m, UINT2& r) + template + INLINE static void usquaremod(const UINT1& a, const UINT2& m, UINT3& r) { - struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), alignof(UINT2)))) MEM { + struct alignas(MAX(alignof(size_t), MAX(alignof(UINT1), MAX(alignof(UINT2), alignof(UINT3))))) MEM { Padded a1; Padded a2; size_t p; From 44cd6cd97a3d66228293284eaa1d1863d268d9d2 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Fri, 31 Jul 2026 17:50:15 +0200 Subject: [PATCH 4/6] wip --- include/CppCore/Math/Util.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index 710b7bf2..927301cb 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3531,14 +3531,18 @@ namespace CppCore CppCore::clone(r, tr.v); } #if defined(CPPCORE_CPU_X64) - else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) == 8) + else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) == 8 && sizeof(UINT3) >= 8) { + if constexpr (sizeof(UINT3) > 8) + CppCore::clear(r); constexpr uint32_t N64 = sizeof(UINT1) / 8; *(uint64_t*)&r = CppCore::umod128_64x((uint64_t*)&u, v, N64); } #endif - else if constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) == 4) + else if constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) == 4 && sizeof(UINT3) >= 4) { + if constexpr (sizeof(UINT3) > 4) + CppCore::clear(r); constexpr uint32_t N32 = sizeof(UINT1) / 4; *(uint32_t*)&r = CppCore::umod64_32x((uint32_t*)&u, v, N32); } From f325a9f5aceb4b63ceaa1e562d79c64f5c7753e3 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Fri, 31 Jul 2026 17:55:31 +0200 Subject: [PATCH 5/6] wip --- include/CppCore/Math/Util.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index 927301cb..f4256789 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3500,7 +3500,13 @@ namespace CppCore INLINE static void umod(UINT3& r, const UINT1& u, const UINT2& v, MEM& mem) { static_assert(sizeof(UINT1) != 0 && sizeof(UINT2) != 0 && sizeof(UINT3) != 0 && sizeof(MEM) != 0); - if constexpr (sizeof(UINT1) < sizeof(size_t)) + if constexpr (sizeof(UINT3) < sizeof(size_t)) + { + size_t tr; + CppCore::umod(tr, u, v, mem); + CppCore::clone(r, *(UINT3*)&tr); + } + else if constexpr (sizeof(UINT1) < sizeof(size_t)) { CppCore::umod(r, (size_t)u, v, mem); } @@ -3508,11 +3514,11 @@ namespace CppCore { CppCore::umod(r, u, (size_t)v, mem); } - else if constexpr (sizeof(UINT3) < sizeof(size_t)) + else if constexpr (sizeof(UINT3) % sizeof(size_t) != 0) { - size_t tr; + Padded tr; CppCore::umod(tr, u, v, mem); - CppCore::clone(r, *(UINT3*)&tr); + CppCore::clone(r, tr.v); } else if constexpr (sizeof(UINT1) % sizeof(size_t) != 0) { @@ -3524,12 +3530,6 @@ namespace CppCore Padded tv(v); CppCore::umod(r, u, tv, mem); } - else if constexpr (sizeof(UINT3) % sizeof(size_t) != 0) - { - Padded tr; - CppCore::umod(tr, u, v, mem); - CppCore::clone(r, tr.v); - } #if defined(CPPCORE_CPU_X64) else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) == 8 && sizeof(UINT3) >= 8) { From ea1fd949a3457e9b4cda7e8eafb085fe3a443a96 Mon Sep 17 00:00:00 2001 From: Clint Banzhaf Date: Fri, 31 Jul 2026 18:03:46 +0200 Subject: [PATCH 6/6] wip --- include/CppCore/Math/Util.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/CppCore/Math/Util.h b/include/CppCore/Math/Util.h index f4256789..74d3784f 100644 --- a/include/CppCore/Math/Util.h +++ b/include/CppCore/Math/Util.h @@ -3531,7 +3531,7 @@ namespace CppCore CppCore::umod(r, u, tv, mem); } #if defined(CPPCORE_CPU_X64) - else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) == 8 && sizeof(UINT3) >= 8) + else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) == 8 && sizeof(UINT3) % 8 == 0) { if constexpr (sizeof(UINT3) > 8) CppCore::clear(r); @@ -3539,7 +3539,7 @@ namespace CppCore *(uint64_t*)&r = CppCore::umod128_64x((uint64_t*)&u, v, N64); } #endif - else if constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) == 4 && sizeof(UINT3) >= 4) + else if constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) == 4 && sizeof(UINT3) % 4 == 0) { if constexpr (sizeof(UINT3) > 4) CppCore::clear(r); @@ -3547,7 +3547,7 @@ namespace CppCore *(uint32_t*)&r = CppCore::umod64_32x((uint32_t*)&u, v, N32); } #if defined(CPPCORE_CPU_X64) - else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) % 8 == 0) + else if constexpr (sizeof(UINT1) % 8 == 0 && sizeof(UINT2) % 8 == 0 && sizeof(UINT3) % 8 == 0) { // using 64-bit chunks assert((void*)&r != (void*)&v); @@ -3660,8 +3660,8 @@ namespace CppCore else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); } } - else #endif + else if constexpr (sizeof(UINT1) % 4 == 0 && sizeof(UINT2) % 4 == 0 && sizeof(UINT3) % 4 == 0) { // using 32-bit chunks assert((void*)&r != (void*)&v); @@ -3774,6 +3774,7 @@ namespace CppCore else CppCore::clone(*(UINT1*)&r, *(UINT1*)&mem); } } + else assert(false); } ///