Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
math_nt_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
36# include <gtest/gtest.h>
37# include <chrono>
38# include <cstdlib>
39# include <random>
40# include <algorithm>
41# include <numeric>
42# include <modular_arithmetic.H>
43
44# include <primality.H>
45# include <pollard_rho.H>
47# include <modular_linalg.H>
48# include <tpl_dynMat.H>
49
50using namespace Aleph;
51
53{
54 uint64_t m = 1000000007;
55 EXPECT_EQ(mod_mul(2, 3, m), 6);
56 EXPECT_EQ(mod_exp(2, 10, m), 1024);
57
58 // Test mod_exp with m = 1
59 EXPECT_EQ(mod_exp(2, 10, 1), 0ULL);
60 EXPECT_EQ(mod_exp(2, 0, 1), 0ULL);
61
62 uint64_t big_m = 4000000000000000000ULL; // > 32 bits
63 uint64_t a = 3000000000000000000ULL;
64 uint64_t b = 2000000000000000000ULL;
65 // 3e18 * 2e18 = 6e36
66 // 6e36 % 4e18 = 0
67 EXPECT_EQ(mod_mul(a, b, big_m), 0ULL);
68
69 EXPECT_EQ(mod_mul(a + 1, b, big_m), 2000000000000000000ULL);
70}
71
73{
74 int64_t x, y;
75 int64_t g = ext_gcd<int64_t>(30, 20, x, y);
76 EXPECT_EQ(g, 10);
77 EXPECT_EQ(30 * x + 20 * y, 10);
78
79 EXPECT_EQ(mod_inv(3, 11), 4); // 3 * 4 = 12 = 1 mod 11
80 EXPECT_THROW(mod_inv(2, 4), std::invalid_argument);
81}
82
84{
85 Array<uint64_t> rem = {2, 3, 2};
86 Array<uint64_t> mod = {3, 5, 7};
87 // x = 2 mod 3
88 // x = 3 mod 5
89 // x = 2 mod 7
90 // Answer is 23
91 EXPECT_EQ(crt(rem, mod), 23);
92}
93
95{
102 EXPECT_TRUE(miller_rabin(1000000007));
103 EXPECT_TRUE(miller_rabin(2147483647));
104
105 // Property-based checks with fixed seed
106 std::mt19937_64 rng(42);
107 for (int i = 0; i < 100; ++i)
108 {
109 uint64_t n = rng() % 1000000;
110 if (n < 2) continue;
111 bool is_p = miller_rabin(n);
112
113 // Simple primality oracle for validation
114 bool oracle = true;
115 for (uint64_t d = 2; d * d <= n; ++d)
116 if (n % d == 0) { oracle = false; break; }
117 EXPECT_EQ(is_p, oracle) << "n=" << n;
118 }
119}
120
122{
123 auto factors = pollard_rho(12);
124 Array<uint64_t> exp12 = {2, 2, 3};
126
127 auto factors_prime = pollard_rho(97);
128 Array<uint64_t> exp97 = {97};
130
131 auto big_factors = pollard_rho(1000000007ULL * 97ULL);
132 Array<uint64_t> exp_big = {97, 1000000007};
134
135 // Randomized property check
136 std::mt19937_64 rng(1337);
137 for (int i = 0; i < 20; ++i)
138 {
139 uint64_t n = rng() % 1000000000000ULL + 2;
140 auto res = pollard_rho(n);
141
142 uint64_t prod = 1;
143 for (const auto f : res)
144 {
145 EXPECT_TRUE(miller_rabin(f)) << "Factor " << f << " of " << n << " is not prime";
146 prod *= f;
147 }
148 EXPECT_EQ(prod, n) << "Product of factors doesn't match original n";
149 }
150}
151
153{
154 if (not std::getenv("ENABLE_PERF_TESTS"))
155 GTEST_SKIP() << "Skipping performance regression (set ENABLE_PERF_TESTS to enable)";
156
157 // 1. Pollard Rho on a large composite (product of two 31-bit primes)
158 uint64_t p1 = 2147483647; // prime
159 uint64_t p2 = 1000000007; // prime
160 uint64_t n = p1 * p2;
161
162 auto start = std::chrono::steady_clock::now();
163 auto factors = pollard_rho(n);
164 auto end = std::chrono::steady_clock::now();
165
166 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
167
168 EXPECT_EQ(factors.size(), 2);
169 EXPECT_TRUE(std::find(factors.begin(), factors.end(), p1) != factors.end());
170 EXPECT_TRUE(std::find(factors.begin(), factors.end(), p2) != factors.end());
171
172 EXPECT_LE(duration, 500) << "Pollard-Rho performance regression detected";
173
174}
175
177{
178 ModularCombinatorics mc(10, 1000000007);
179 EXPECT_EQ(mc.nCk(5, 2), 10);
180 EXPECT_EQ(mc.nCk(5, 0), 1);
181 EXPECT_EQ(mc.nCk(5, 6), 0);
182 EXPECT_EQ(mc.nCk(0, 0), 1);
183 EXPECT_EQ(mc.nCk(10, 5), 252);
184
185 // Bounds check
186 EXPECT_THROW(mc.nCk(11, 2), std::out_of_range);
187
188 // Lucas Theorem test
189 ModularCombinatorics mc_small(10, 3); // Modulo 3
190 // C(5, 2) = 10 = 1 mod 3
191 EXPECT_EQ(mc_small.lucas_nCk(5, 2), 1);
192 EXPECT_EQ(mc_small.lucas_nCk(5, 0), 1);
193 EXPECT_EQ(mc_small.lucas_nCk(0, 0), 1);
194}
195
197{
200 m_data.append(Array<uint64_t>({3, 4}));
201
202 ModularMatrix mat(m_data, 5); // modulo 5
203 // det = 1*4 - 2*3 = 4 - 6 = -2 = 3 mod 5
204 EXPECT_EQ(mat.determinant(), 3);
205
206 auto inv_opt = mat.inverse();
207 ASSERT_TRUE(inv_opt.has_value());
208 auto inv_mat = inv_opt->get();
209
210 // Check A^-1 * A = I
211 EXPECT_EQ((inv_mat[0][0] * 1 + inv_mat[0][1] * 3) % 5, 1);
212 EXPECT_EQ((inv_mat[0][0] * 2 + inv_mat[0][1] * 4) % 5, 0);
213 EXPECT_EQ((inv_mat[1][0] * 1 + inv_mat[1][1] * 3) % 5, 0);
214 EXPECT_EQ((inv_mat[1][0] * 2 + inv_mat[1][1] * 4) % 5, 1);
215}
216
218{
219 // Sparse matrix with DynMatrix
221 m_data.write(0, 0, 2);
222 m_data.write(1, 1, 3);
223 m_data.write(2, 2, 4);
224
225 ModularSparseMatrix mat(m_data, 7); // modulo 7
226 // det = 2*3*4 = 24 = 3 mod 7
227 EXPECT_EQ(mat.determinant(), 3);
228
229 auto inv_opt = mat.inverse();
230 ASSERT_TRUE(inv_opt.has_value());
231 auto inv_mat = inv_opt->get();
232
233 // Inverses of 2, 3, 4 mod 7 are 4, 5, 2
234 EXPECT_EQ(inv_mat.read(0, 0), 4);
235 EXPECT_EQ(inv_mat.read(1, 1), 5);
236 EXPECT_EQ(inv_mat.read(2, 2), 2);
237 EXPECT_EQ(inv_mat.read(0, 1), 0);
238}
239
241{
242 // Matrix that requires a row swap for pivoting
243 // [ 0 1 ]
244 // [ 1 1 ] mod 5
246 m_data.write(0, 1, 1);
247 m_data.write(1, 0, 1);
248 m_data.write(1, 1, 1);
249
251 // det = 0*1 - 1*1 = -1 = 4 mod 5
252 EXPECT_EQ(mat.determinant(), 4);
253
254 auto inv_opt = mat.inverse();
255 ASSERT_TRUE(inv_opt.has_value());
256 auto inv_mat = inv_opt->get();
257
258 // Check inverse: [ 4 1 ] [ 0 1 ] = [ 1 0 ]
259 // [ 1 0 ] [ 1 1 ] = [ 0 1 ]
260 EXPECT_EQ(inv_mat.read(0, 0), 4);
261 EXPECT_EQ(inv_mat.read(0, 1), 1);
262 EXPECT_EQ(inv_mat.read(1, 0), 1);
263 EXPECT_EQ(inv_mat.read(1, 1), 0);
264}
265
267{
268 // Singular matrix
269 // [ 1 2 ]
270 // [ 2 4 ] mod 7
272 m_data.write(0, 0, 1);
273 m_data.write(0, 1, 2);
274 m_data.write(1, 0, 2);
275 m_data.write(1, 1, 4);
276
278 EXPECT_EQ(mat.determinant(), 0);
279 EXPECT_FALSE(mat.inverse().has_value());
280}
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
Dynamic matrix with sparse storage.
Definition tpl_dynMat.H:120
Combinatorics operations modulo a prime.
Matrix operations modulo a prime.
uint64_t determinant() const
Computes the determinant of the matrix modulo p.
std::optional< Modular_Matrix< MatrixT > > inverse() const
Computes the inverse of the matrix modulo p.
#define TEST(name)
static mt19937 rng
Safe modular arithmetic, extended Euclidean algorithm, and Chinese Remainder Theorem.
Modular combinatorics utilities.
Linear algebra operations over finite fields (modulo a prime).
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
uint64_t mod_inv(const uint64_t a, const uint64_t m)
Modular Inverse.
Array< uint64_t > pollard_rho(uint64_t n)
Compute the prime factorization of a number using Pollard's rho.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
bool miller_rabin(uint64_t n) noexcept
Miller-Rabin primality test for 64-bit integers.
Definition primality.H:87
uint64_t mod_exp(uint64_t base, uint64_t exp, const uint64_t m)
Modular exponentiation.
uint64_t mod_mul(uint64_t a, uint64_t b, uint64_t m)
Safe 64-bit modular multiplication.
uint64_t crt(const Array< uint64_t > &rem, const Array< uint64_t > &mod)
Chinese Remainder Theorem (CRT).
Integer factorization using Pollard's rho algorithm.
Advanced primality testing algorithms.
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic matrix with lazy allocation.