LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
prime_table.h
浏览该文件的文档.
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#ifndef __LAMMP_PRIME_TABLE_H__
17#define __LAMMP_PRIME_TABLE_H__
18
19#include "../numth.h"
20#include <math.h>
21
22typedef uint64_t lmmp_bitset_t;
23typedef uint64_t* lmmp_bitset_p;
24
25#define LMMP_BITSET_BITS (64)
26#define LMMP_BITSET_MASK (0xffffffffffffffffull)
27#define LMMP_BITSET_BYTES (8)
28
29#define PRIME_SHORT_TABLE_SIZE 6542
30
31#define PRIME_SHORT_TABLE_N 0x10000
32
34
35/**
36 * @brief 根据全局素数表判断一个数是否为素数
37 * @param p 待判断的数
38 * @warning p>1, p%2==1
39 * @note 若 p 超过了当前全局素数表的范围,则返回 -1
40 * @return 1 素数,0 合数,-1 超出质数表范围
41 */
43
44/**
45 * @brief 计算小于等于 n 的素数数量
46 * @param n 范围
47 * @return 素数数量
48 */
50
51/**
52 * @brief 估计 n 范围内的素数数量
53 * @param n 范围
54 * @note 不会低估素数数量,可能恰好超过 pi(n),用以估计素数数组需要的空间
55 * @return 素数数量
56 */
57static inline ulong lmmp_prime_size_(ulong n) {
58 if (n < PRIME_SHORT_TABLE_N) {
59 return lmmp_prime_cnt16_(n);
60 } else if (n < 95000) {
61 return (ulong)ceil((double)n / (log(n) - 1.095)) + 1;
62 } else if (n < 355991) {
63 return (ulong)ceil((double)n / (log(n) - 1.0975)) + 1;
64 } else if (n < 1332479531) {
65 // Dusart 2000 估计 - π(x)的上界
66 // lmmp_debug_assert(n >= 355991);
67 double x = (double)n;
68 double lnx = log(x);
69 double lnx2 = lnx * lnx;
70 double r = x / lnx * (1.0 + 1.0 / lnx + 2.51 / lnx2);
71 return (ulong)r;
72 }
73 /*
74 Dusart 2010 估计 - π(x)的严格上界
75 from: Dusart (2010) "Estimates of some functions over primes without R.H."(https://arxiv.org/abs/1002.0442)
76 U(x) = x / [lnx
77 - 1
78 - 1/lnx
79 - 3.35/(lnx)^2
80 - 12.65/(lnx)^3
81 - 71.7/(lnx)^4
82 - 466.1275/(lnx)^5
83 - 3489.8225/(lnx)^6]
84 */
85 // lmmp_debug_assert(n >= 1332479531);
86 double lnx = log(n);
87 double lnx2 = lnx * lnx;
88 double lnx3 = lnx2 * lnx;
89 double lnx4 = lnx3 * lnx;
90 double lnx5 = lnx4 * lnx;
91 double lnx6 = lnx5 * lnx;
92
93 double denom =
94 lnx - 1.0 - 1.0 / lnx - 3.35 / lnx2 - 12.65 / lnx3 - 71.7 / lnx4 - 466.1275 / lnx5 - 3489.8225 / lnx6;
95
96 return (ulong)ceil(n / denom);
97}
98
99/**
100 * @brief 初始化全局素数表
101 * @param n 素数表大小(含n)
102 */
104
105/**
106 * @brief 释放全局素数表
107 */
109
110typedef struct {
111 uintp pp; // 仅存储奇素数
112 uint size; // pp 数组大小
113 uint start_idx; // 位图下一次解析的起始索引(字)
114 uint end_idx; // 位图应该终止解析的结束索引(字)
115 uint end_num; // 终止解析的最大数
116 int is_end; // 是否已经遍历到全局质数表末尾
118
119/*
120 示例代码(遍历全局奇素数表):
121
122 lmmp_prime_int_table_init_(n);
123 prime_cache_t cache;
124 lmmp_prime_cache_init_(&cache, n);
125 while (cache.is_end == 0) {
126 lmmp_prime_cache_next_(&cache);
127 for (uint i = 0; i < cache.size; i++) {
128 ....
129 }
130 }
131 lmmp_prime_cache_free_(&cache);
132*/
133
134/**
135 * @brief 初始化素数表缓存
136 * @param cache 缓存结构体
137 * @param n 遍历素数表的范围(超过n时或者遍历到全局质数表末尾,is_end 置为 1)
138 */
140
141/**
142 * @brief 素数表缓存更新(从小到大遍历全局质数表)
143 * @param cache 缓存结构体
144 * @note 缓存只存储奇素数,当遍历到全局质数表末尾或者达到设置的范围时,is_end 置为 1
145 */
147
148/**
149 * @brief 释放素数表缓存
150 * @param cache 缓存结构体
151 */
153
154// 3,5,7,11的余数掩码表
155extern const lmmp_bitset_t r35711_mask_map[19];
156
157/**
158 * @brief 校验是否能被3,5,7,11整除,能够整除则返回1,否则返回0
159 */
160static inline int trial_div35711(ulong n) {
161 uint rem = n % 1155; // 1155 = 3 * 5 * 7 * 11
162 uint idx = rem / LMMP_BITSET_BITS;
163 uint bit = rem % LMMP_BITSET_BITS;
164 return (r35711_mask_map[idx] >> bit) & 1ULL;
165}
166
167#endif // __LAMMP_PRIME_TABLE_H__
#define n
uint32_t uint
Definition numth.h:31
uint32_t * uintp
Definition numth.h:39
uint16_t ushort
Definition numth.h:29
uint64_t ulong
Definition numth.h:32
uint64_t lmmp_bitset_t
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition prime_table.h:22
static int trial_div35711(ulong n)
校验是否能被3,5,7,11整除,能够整除则返回1,否则返回0
void lmmp_prime_cache_free_(prime_cache_t *cache)
释放素数表缓存
#define PRIME_SHORT_TABLE_SIZE
Definition prime_table.h:29
const lmmp_bitset_t r35711_mask_map[19]
void lmmp_prime_cache_next_(prime_cache_t *cache)
素数表缓存更新(从小到大遍历全局质数表)
uint64_t * lmmp_bitset_p
Definition prime_table.h:23
void lmmp_prime_int_table_free_(void)
释放全局素数表
#define LMMP_BITSET_BITS
Definition prime_table.h:25
static ulong lmmp_prime_size_(ulong n)
估计 n 范围内的素数数量
Definition prime_table.h:57
int lmmp_is_prime_table_(uint p)
根据全局素数表判断一个数是否为素数
#define PRIME_SHORT_TABLE_N
Definition prime_table.h:31
const ushort prime_short_table[6542]
void lmmp_prime_int_table_init_(uint n)
初始化全局素数表
Definition prime_table.c:99
ushort lmmp_prime_cnt16_(ushort n)
计算小于等于 n 的素数数量
void lmmp_prime_cache_init_(prime_cache_t *cache, uint n)
初始化素数表缓存