contributed by < linjohnss >
1
實作利用 Sieve of Eratosthenes,嘗試找出第 1500 個回文質數,有效位數是 15
給定要找的質數範圍 n,找出 \(\sqrt n\) 內的所有質數,並依序剔除每著質數在範圍 n 內的所有倍數,留下來的數字即為和為內的所有質數。
static ull pow10[] = {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
};
static inline ull fastpow10(const int n)
{
if (n < 0 || n > 16) {
free(psieve);
printf("n = %d\n", n);
exit(1);
}
return pow10[n];
}
fastpow10
用查表的方式,找出 10 的冪
後續會用來快速配置 100...001
/* isqrt64_tab[k] = isqrt(256 * (k + 65) - 1) for 0 <= k < 192 */
static const uint8_t isqrt64_tab[192] = {
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 143, 144, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155,
155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167,
167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176, 177, 178,
178, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188,
189, 189, 190, 191, 191, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198,
199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206, 207, 207,
208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215, 215, 216, 217,
217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223, 223, 224, 225, 225,
226, 226, 227, 227, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 234,
234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242,
242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249,
250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
};
/* integer square root of a 64-bit unsigned integer */
static ull isqrt(ull x)
{
if (x == 0)
return 0;
int lz = __builtin_clzll(x) & 62;
x <<= lz;
uint32_t y = isqrt64_tab[(x >> 56) - 64];
y = (y << 7) + (x >> 41) / y;
y = (y << 15) + (x >> 17) / y;
y -= x < (uint64_t) y * y;
return y >> (lz >> 1);
}
isqrt
利用 lookup table (LUT) 的手法實做整數開平方根,用於找到 sieve of Eratosthenes 演算法的 \(\sqrt n\)
static void generate_sieve(int digits)
{
ull max = 0;
for (int count = 0; count < digits; ++count)
max = max * 10 + 9;
max = isqrt(max);
half_max = max >> 1;
/* We need half the space as multiples of 2 can be omitted */
int bytes = (max >> 1) + (max & 0x1);
/* Calculate the actual number of bytes required */
bytes = (bytes >> 3) + (bytes & 0x1);
bytes = ALIGN(bytes, 16); /* Align-up to 16-byte */
psieve = realloc(psieve, bytes);
if (!psieve) {
printf("realloc() failed!\n");
exit(1);
}
memset(psieve, 0, bytes);
/* In psieve bit 0 -> 1, 1 -> 3, 2 -> 5, 3 -> 7 and so on... */
/* Set the 0th bit representing 1 to COMPOSITE
*/
psieve[0] |= COMPOSITE << (1 >> 1);
unsigned char mask = 0x7;
for (ull n = 3; n <= max; n += 2) {
if (((psieve[n >> 4] >> ((n >> 1) & mask)) & 0x1) == PRIME) {
for (ull mul = (n << 1); mul < max; mul += n) {
/* Skip the evens: there is no representation in psieve */
if (!(mul & 0x1))
continue;
/* Set offset of mul in psieve */
psieve[mul >> 4] |= COMPOSITE
<< ((mul >> 1) & mask); /* bit offset */
}
}
}
}
根據位數 digits
產生對應的 bitmaps psieve
static bool isprime(const ull val)
{
if (!(val & 0x1)) /* Test for divisibility by 2 */
return false;
ull *pquadbits = (ull *) psieve;
ull next = 3; /* start at 7 (i.e. 3 * 2 + 1) */
for (ull quad = ~*pquadbits & ~0b111, prev = 0; prev <= half_max;
quad = ~*++pquadbits) {
if (!quad) {
prev += 64;
continue;
}
while (quad) {
ull i = EXP1;
next = prev + i;
if (!(val % ((next << 1) + 1)))
return false;
quad &= EXP2;
}
prev += 64;
}
return true;
}
判斷是否為質數
half_max
__builtin_ctzll
來找出左邊第一格 1 之前的 0 的個數,進而推出 next
EXP1
= __builtin_ctzll(quad)
quad
標注已檢查的質數為 0,利用 i 代表位數與 quad
作 AND 運算
EXP2
= ~(1ULL << i)
TODO:
是否有必要先將數值轉成字串?用十進位的角度處理運算是否產生額外的計算負擔?
2
contributed by < linjohnss > GitHub: rcuhashbash 目標 Linux 核心提供一套 Resizable, Scalable, Concurrent Hash Table,名為 rhashtable (見 include/linux/rhashtable.h 及 lib/rhashtable.c),描述於論文〈Resizable, Scalable, Concurrent Hash Tables via Relativistic Programming〉。摘譯 LWN 文章,並佐以原論文,描述 rhashtable 何以落實高效的並行雜湊表,搭配撰寫 Linux 核心模組作為試驗 Relativistic hash tables, part 1: Algorithms hash table 在 Linux 的應用場景 在 Linux 的 file system 中,利用 hash table 儲存 mount 的 root dentry ,因此 lookup_mount 可以利用 hash_get 取得 mount 的 root dentry
Jun 11, 2023contributed by < linjohnss > 2022q1 第 6 週測驗題 測驗 1 利用 clone 實做 user level 的 thread 函式庫 程式碼實做原理 函數使用
Jun 13, 2022contributed by < linjohnss > 作業要求 自我檢查清單 [ ] 研讀上述 ==Linux 效能分析的提示== 描述,在自己的實體電腦運作 GNU/Linux,做好必要的設定和準備工作 $\to$ 從中也該理解為何不希望在虛擬機器中進行實驗; [ ] 研讀上述費氏數列相關材料 (包含論文),摘錄關鍵手法,並思考 clz / ctz 一類的指令對 Fibonacci 數運算的幫助。請列出關鍵程式碼並解說 [ ] 複習 C 語言 數值系統 和 bitwise operation,思考 Fibonacci 數快速計算演算法的實作中如何減少乘法運算的成本; [ ] 研讀 KYG-yaya573142 的報告,指出針對大數運算,有哪些加速運算和縮減記憶體操作成本的舉措?
Apr 27, 2022測驗題目 測驗 1 程式碼運作原理 功能 輸入大於 0 的無號整數,計算 $\lceil log_2(x) \rceil$ 實做 int ceil_log2(uint32_t x) {
Mar 29, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up