LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
is_prime_ulong.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../include/lammp/impl/is_prime_table.h"
17#include "../../../include/lammp/impl/prime_table.h"
18#include "../../../include/lammp/impl/longlong.h"
19#include "../../../include/lammp/impl/mparam.h"
20#include "../../../include/lammp/lmmpn.h"
21#include "../../../include/lammp/numth.h"
22
23/*
24mont63 只能用于小于 2^63 的数,否则会溢出导致计算结果不正确
25mont64 可以用于任意大小的数,但由于考虑了溢出的情况,所以速度理论上会慢一些(并未详细测试)
26*/
27#define MONT63_MAX ((ulong)(0x7fffffffffffffff))
28
30 ulong k = t[0] * m_inv;
31 u192 tmp;
32 _u128mul(tmp, k, m);
33 tmp[0] += t[0];
34 ulong c = tmp[0] < t[0];
35 tmp[1] += c;
36 c = tmp[1] == 0;
37 tmp[1] += t[1];
38 c = tmp[1] < t[1];
39 tmp[2] = c;
40 if (!c) {
41 ulong res = tmp[1] >= m ? tmp[1] - m : tmp[1];
42 return res;
43 } else {
44 _u128sub64(tmp + 1, tmp + 1, m);
45 return tmp[1];
46 }
47}
48
49static inline ulong mont64_R2(ulong m) {
50 u192 r = {0, 0, 1};
51 u128 q;
52 lmmp_div_1_s_(q, r, 3, m);
53 return r[0];
54}
55
57 u128 t;
58 _u128mul(t, x, R2);
59 return mont64_reduce(t, m, m_inv);
60}
61
63 u128 t = {x, 0};
64 return mont64_reduce(t, m, m_inv);
65}
66
68 u128 t;
69 _u128mul(t, a, b);
70 return mont64_reduce(t, m, m_inv);
71}
72
74 ulong k = t[0] * m_inv;
75 u128 tmp;
76 _u128mul(tmp, k, m);
77 _u128add(tmp, tmp, t);
78 ulong res = tmp[1] >= m ? tmp[1] - m : tmp[1];
79 return res;
80}
81
82static inline ulong mont63_R2(ulong m) {
85 u192 r = {0, 0, 1ull << shift};
86 u128 q;
87 lmmp_div_1_s_(q, r, 3, m);
88 return r[0] >> shift;
89}
90
92 u128 t;
93 _u128mul(t, x, R2);
94 return mont63_reduce(t, m, m_inv);
95}
96
98 u128 t = {x, 0};
99 return mont63_reduce(t, m, m_inv);
100}
101
103 u128 t;
104 _u128mul(t, a, b);
105 return mont63_reduce(t, m, m_inv);
106}
107
109 lmmp_param_assert(mod > base);
111 ulong dst = 1;
112 ulong b = base;
114 ulong q;
115 while (1) {
116 if (exp & 1) {
117 dst *= b;
119 dst -= q * mod;
120 }
121 exp >>= 1;
122 if (exp == 0)
123 break;
124 b *= b;
126 b -= q * mod;
127 }
128 return dst;
129}
130
132 if (mod <= MP_UINT_MAX)
133 return lmmp_powmod_uint_(base, exp, mod);
134 else if (mod <= MONT63_MAX) {
137 m_inv = -m_inv;
138 ulong dst = to_mont63(1, R2, mod, m_inv);
139 base = to_mont63(base, R2, mod, m_inv);
140 while (1) {
141 if (exp & 1)
142 dst = mont63_mul(dst, base, mod, m_inv);
143 exp >>= 1;
144 if (exp == 0)
145 break;
146 base = mont63_mul(base, base, mod, m_inv);
147 }
148 return from_mont63(dst, mod, m_inv);
149 } else {
152 m_inv = -m_inv;
153 ulong dst = to_mont64(1, R2, mod, m_inv);
154 base = to_mont64(base, R2, mod, m_inv);
155 while (1) {
156 if (exp & 1)
157 dst = mont64_mul(dst, base, mod, m_inv);
158 exp >>= 1;
159 if (exp == 0)
160 break;
161 base = mont64_mul(base, base, mod, m_inv);
162 }
163 return from_mont64(dst, mod, m_inv);
164 }
165}
166
168 ulong v = 1;
169 ulong base = a;
170 ulong q;
171 while (1) {
172 if (u & 1) {
173 v *= base;
175 v -= q * m;
176 }
177 u >>= 1;
178 if (u == 0)
179 break;
180 base *= base;
181 q = _udiv64by64_q_preinv(base, binv);
182 base -= q * m;
183 }
184
185 if (v == 1 || v == m - 1)
186 return 1;
187 for (ulong j = 1; j < t; ++j) {
188 v *= v;
190 v -= q * m;
191 if (v == m - 1)
192 return 1;
193 if (v == 1)
194 return 0;
195 }
196 return 0;
197}
198
200 ulong v = one;
201 ulong base = a;
202 while (1) {
203 if (u & 1)
204 v = mont63_mul(v, base, m, m_inv);
205 u >>= 1;
206 if (u == 0)
207 break;
208 base = mont63_mul(base, base, m, m_inv);
209 }
210 if (v == one || v == m_1)
211 return 1;
212
213 for (ulong j = 1; j < t; ++j) {
214 v = mont63_mul(v, v, m, m_inv);
215 if (v == m_1)
216 return 1;
217 if (v == one)
218 return 0;
219 }
220 return 0;
221}
222
224 ulong v = one;
225 ulong base = a;
226 while (1) {
227 if (u & 1)
228 v = mont64_mul(v, base, m, m_inv);
229 u >>= 1;
230 if (u == 0)
231 break;
232 base = mont64_mul(base, base, m, m_inv);
233 }
234 if (v == one || v == m_1)
235 return 1;
236 for (ulong j = 1; j < t; ++j) {
237 v = mont64_mul(v, v, m, m_inv);
238 if (v == m_1)
239 return 1;
240 if (v == one)
241 return 0;
242 }
243 return 0;
244}
245
246/*******************************************************************************
247 * from http://probableprime.org/download/example-primality.c
248 * Deterministic Miller-Rabin tests for 64-bit.
249 * Hashed 2-bases for n < 684630005672341 (slightly more than 2^49)
250 * Hashed 3-bases for n < 2^64
251 *
252 * Based on Steve Worley's 2^32 example:
253 * http://www.mersenneforum.org/showthread.php?t=12209
254 * With a 3-base encoding idea from Bradley Berg.
255 *
256 * Copyright 2014, Dana Jacobsen <[email protected]>
257 *******************************************************************************/
258
260 if (n % 2 == 0 || n <= 1)
261 return false;
263 if (judge == 0) {
264 return false;
265 } else if (judge == 1) {
266 return true;
267 }
268
269 if (trial_div35711(n))
270 return false;
271
272 ushort bases[2];
273 bases[0] = 2;
274 bases[1] = dj_base49[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 21] + 3;
275 if (n % bases[0] == 0)
276 return false;
277 if (n % bases[1] == 0)
278 return false;
279
280 ulong u = n - 1, t = 0;
281 while (u % 2 == 0) u /= 2, ++t;
282
284 if (miller_rabin_32(bases[0], t, u, n, &binv))
285 if (miller_rabin_32(bases[1], t, u, n, &binv))
286 return true;
287 else
288 return false;
289 else
290 return false;
291}
292
294 lmmp_param_assert(n > 1);
295 if (n < 684630005672341) {
296 ushort bases[2];
297 bases[0] = 2;
298 bases[1] = dj_base49[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 21] + 3;
299 if (n % bases[0] == 0)
300 return false;
301 if (n % bases[1] == 0)
302 return false;
303
304 ulong one = 1;
305 ulong m_1 = n - 1;
307 m_inv = -m_inv;
308 ulong R2 = mont63_R2(n);
309 one = to_mont63(one, R2, n, m_inv);
310 m_1 = to_mont63(m_1, R2, n, m_inv);
311
312 ulong u = n - 1, t = 0;
313 while (u % 2 == 0) u /= 2, ++t;
314
315 if (miller_rabin_63(bases[0], t, u, n, m_inv, one, m_1))
316 if (miller_rabin_63(bases[1], t, u, n, m_inv, one, m_1))
317 return true;
318 else
319 return false;
320 else
321 return false;
322 } else {
323 ushort bases[3];
324 ulong bbmask = dj_base64[((0x3AC69A35UL * n) & 0xFFFFFFFFUL) >> 18];
325 bases[0] = 2;
326 bases[1] = (bbmask & 0x8000) ? 26460 : 9375;
327 bases[2] = (bbmask & 0x7FFF) + 3;
328
329 if (n % bases[0] == 0)
330 return false;
331 if (n % bases[1] == 0)
332 return false;
333 if (n % bases[2] == 0)
334 return false;
335
336 ulong one = 1;
337 ulong m_1 = n - 1;
339 m_inv = -m_inv;
340
341 if (n <= MONT63_MAX) {
342 ulong R2 = mont63_R2(n);
343 one = to_mont63(one, R2, n, m_inv);
344 m_1 = to_mont63(m_1, R2, n, m_inv);
345
346 ulong u = n - 1, t = 0;
347 while (u % 2 == 0) u /= 2, ++t;
348
349 if (miller_rabin_63(bases[0], t, u, n, m_inv, one, m_1))
350 if (miller_rabin_63(bases[1], t, u, n, m_inv, one, m_1))
351 if (miller_rabin_63(bases[2], t, u, n, m_inv, one, m_1))
352 return true;
353 else
354 return false;
355 else
356 return false;
357 else
358 return false;
359 } else {
360 ulong R2 = mont64_R2(n);
361 one = to_mont64(one, R2, n, m_inv);
362 m_1 = to_mont64(m_1, R2, n, m_inv);
363
364 ulong u = n - 1, t = 0;
365 while (u % 2 == 0) u /= 2, ++t;
366
367 if (miller_rabin_64(bases[0], t, u, n, m_inv, one, m_1))
368 if (miller_rabin_64(bases[1], t, u, n, m_inv, one, m_1))
369 if (miller_rabin_64(bases[2], t, u, n, m_inv, one, m_1))
370 return true;
371 else
372 return false;
373 else
374 return false;
375 else
376 return false;
377 }
378 }
379}
380
382 if (n % 2 == 0 || n <= 1)
383 return false;
385 if (judge == 0) {
386 return false;
387 } else if (judge == 1) {
388 return true;
389 }
390 if (trial_div35711(n))
391 return false;
393}
394
395static inline bool trial_div13(ulong n) {
396 const _udiv64_t div13 = {.magic = 4256940940086819604ull, .more = 3};
398 n -= q * 13;
399 return n == 0;
400}
401
402static inline bool trial_div17(ulong n) {
403 const _udiv64_t div17 = {.magic = 16276538888567251426ull, .more = 4};
405 n -= q * 17;
406 return n == 0;
407}
408
409static inline bool trial_div19(ulong n) {
410 const _udiv64_t div19 = {.magic = 12621456471485482685ull, .more = 4};
412 n -= q * 19;
413 return n == 0;
414}
415
416static inline bool trial_div23(ulong n) {
417 const _udiv64_t div23 = {.magic = 7218291159277650633ull, .more = 4};
419 n -= q * 23;
420 return n == 0;
421}
422
423static inline bool trial_div29(ulong n) {
424 const _udiv64_t div29 = {.magic = 1908283869694091547ull, .more = 4};
426 n -= q * 29;
427 return n == 0;
428}
429
430static inline bool trial_div31(ulong n) {
431 const _udiv64_t div31 = {.magic = 595056260442243601ull, .more = 4};
433 n -= q * 31;
434 return n == 0;
435}
436
437static inline bool trial_div37(ulong n) {
438 const _udiv64_t div37 = {.magic = 13461137567301564693ull, .more = 5};
440 n -= q * 37;
441 return n == 0;
442}
443
444static inline bool trial_div41(ulong n) {
445 const _udiv64_t div41 = {.magic = 10348173504763894809ull, .more = 5};
447 n -= q * 41;
448 return n == 0;
449}
450
451// 64位内最大的质数
452#define ULONG_PRIME_MAX 0xFFFFFFFFFFFFFFC5ull
453#define ULONG_PRIME_MIN 2
454
458 return prime_short_table[idx];
459 } else if (n >= ULONG_PRIME_MAX) {
460 return MP_ULONG_MAX;
461 } else {
462 n += (n % 2 == 0) ? 1 : 2;
463 while (1) {
464 if (trial_div35711(n)
465 || trial_div13(n)
466 || trial_div17(n)
467 || trial_div19(n)
468 || trial_div23(n)
469 || trial_div29(n)
470 || trial_div31(n)
471 || trial_div37(n)
472 || trial_div41(n)) {
473 n += 2;
474 } else {
476 return n;
477 } else {
478 n += 2;
479 }
480 }
481 }
482 }
483}
484
486 if (n < ULONG_PRIME_MIN) {
487 return 0;
488 } else if (n < PRIME_SHORT_TABLE_N) {
490 return prime_short_table[idx - 1];
491 } else {
492 n -= (n % 2 == 0) ? 1 : 0;
493 while (1) {
494 if (trial_div35711(n)
495 || trial_div13(n)
496 || trial_div17(n)
497 || trial_div19(n)
498 || trial_div23(n)
499 || trial_div29(n)
500 || trial_div31(n)
501 || trial_div37(n)
502 || trial_div41(n)) {
503 n -= 2;
504 } else {
506 return n;
507 } else {
508 n -= 2;
509 }
510 }
511 }
512 }
513}
#define k
#define c
static const uint16_t dj_base49[2048]
Copyright (C) 2026 HJimmyK(Jericho Knox)
static const uint16_t dj_base64[16384]
static ulong mont63_reduce(u128 t, ulong m, ulong m_inv)
ulong lmmp_prev_prime_ulong_(ulong n)
小于等于n的上一个素数
static bool trial_div31(ulong n)
static ulong mont64_R2(ulong m)
static bool trial_div13(ulong n)
static bool trial_div41(ulong n)
static int miller_rabin_32(ulong a, ulong t, ulong u, uint m, _udiv64_t *binv)
bool lmmp_is_prime_uint_(uint n)
from http://probableprime.org/download/example-primality.c Deterministic Miller-Rabin tests for 64-bi...
#define MONT63_MAX
Copyright (C) 2026 HJimmyK(Jericho Knox)
static ulong to_mont63(ulong x, ulong R2, ulong m, ulong m_inv)
bool lmmp_is_prime_notrial_(ulong n)
判断素数(无试除法)
static bool trial_div29(ulong n)
static bool trial_div37(ulong n)
#define ULONG_PRIME_MIN
static ulong mont63_R2(ulong m)
static ulong from_mont64(ulong x, ulong m, ulong m_inv)
static ulong mont63_mul(ulong a, ulong b, ulong m, ulong m_inv)
uint lmmp_powmod_uint_(uint base, ulong exp, uint mod)
计算 base^exp 对 mod 取模
static int miller_rabin_64(ulong a, ulong t, ulong u, ulong m, ulong m_inv, ulong one, ulong m_1)
ulong lmmp_powmod_ulong_(ulong base, ulong exp, ulong mod)
计算 base^exp 对 mod 取模
static ulong mont64_mul(ulong a, ulong b, ulong m, ulong m_inv)
static ulong from_mont63(ulong x, ulong m, ulong m_inv)
static ulong mont64_reduce(u128 t, ulong m, ulong m_inv)
bool lmmp_is_prime_ulong_(ulong n)
判断素数
#define ULONG_PRIME_MAX
static ulong to_mont64(ulong x, ulong R2, ulong m, ulong m_inv)
static bool trial_div19(ulong n)
static bool trial_div23(ulong n)
ulong lmmp_next_prime_ulong_(ulong n)
大于n的下一个素数
static int miller_rabin_63(ulong a, ulong t, ulong u, ulong m, ulong m_inv, ulong one, ulong m_1)
static bool trial_div17(ulong n)
size_t mp_bitcnt_t
Definition lmmp.h:82
#define lmmp_param_assert(x)
Definition lmmp.h:401
mp_limb_t lmmp_div_1_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_limb_t x)
单精度数除法(除数为1个limb)
#define _u128mul(r, x, y)
Definition longlong.h:375
uint64_t u192[3]
Definition longlong.h:328
#define _u128add(r, x, y)
Definition longlong.h:346
static _udiv64_t _udiv64_gen(uint64_t d)
Definition longlong.h:530
static uint64_t _udiv64by64_q_preinv(uint64_t numer, const _udiv64_t *denom)
Definition longlong.h:536
uint64_t u128[2]
Definition longlong.h:327
#define clz_shl_u64(r, x, cnt)
Definition longlong.h:88
uint64_t magic
Definition longlong.h:472
#define _u128sub64(r, x, _i64)
Definition longlong.h:358
#define MP_UINT_MAX
Definition mparam.h:136
#define MP_ULONG_MAX
Definition mparam.h:137
#define t
#define n
#define tmp
ulong lmmp_binvert_ulong_(ulong a)
计算 a 在2^64下的逆元
Definition binvert_1.c:42
uint32_t uint
Definition numth.h:31
uint16_t ushort
Definition numth.h:29
uint64_t ulong
Definition numth.h:32
static int trial_div35711(ulong n)
校验是否能被3,5,7,11整除,能够整除则返回1,否则返回0
#define PRIME_SHORT_TABLE_SIZE
Definition prime_table.h:29
int lmmp_is_prime_table_(uint p)
根据全局素数表判断一个数是否为素数
#define PRIME_SHORT_TABLE_N
Definition prime_table.h:31
const ushort prime_short_table[6542]
ushort lmmp_prime_cnt16_(ushort n)
计算小于等于 n 的素数数量