2023q1 Homework3 (quiz3)
contributed by < visitorckw
>
2023q1 第 3 週測驗題
測驗 1
測驗 2
測驗 3
Reference: https://zh.wikipedia.org/wiki/线性反馈移位寄存器
LSFR 是一種轉換操作,通常用來生成看起來是隨機的且循環周期非常長的序列。
程式碼中的 log2_64 函數用來計算 的值。運用二分搜的概念,逐步尋找最高位所在的位置。而陣列 log_table_256 用來存放該 index 取 的值,透過巨集 _ 來展開。
static const char log_table_256[256] = {
#define _(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3,
3, 3, 3, 3, 3, _(4), _(5), _(5), _(6), _(6), _(6),
_(6), _(7), _(7), _(7), _(7), _(7), _(7), _(7), _(7),
#undef _
};
#undef _
uint64_t log2_64(uint64_t v)
{
unsigned r;
uint64_t t, tt, ttt;
ttt = v >> 32;
if (ttt) {
tt = ttt >> 16;
if (tt) {
t = tt >> 8;
if (t) {
r = 56 + log_table_256[t];
} else {
r = 48 + log_table_256[tt];
}
} else {
t = ttt >> 8;
if (t) {
r = 40 + log_table_256[t];
} else {
r = 32 + log_table_256[ttt];
}
}
} else {
tt = v >> 16;
if (tt) {
t = tt >> 8;
if (t) {
r = 24 + log_table_256[t];
} else {
r = 16 + log_table_256[tt];
}
} else {
t = v >> 8;
if (t) {
r = 8 + log_table_256[t];
} else {
r = 0 + log_table_256[v];
}
}
}
return r;
}
此函數可以利用 __builtin_clz64 來加速,並且程式碼撰寫上更為簡潔
lsfr 函數用來透過當前狀態轉移得到下一個狀態,new_bit 用來暫存將要放入最左邊的位元,並將其他位元向右位移 1 位。
bucket_number 函數則是會將傳入的參數 x 找到一個對應的 bucket。
mask111 為有效位全為 1 的 bitmask,而 mask011 則為 mask111 的最高位改設為 0 的 bitmask 。
程式會判斷 x & mask111 是否小於 bucket 的數量。
- 若 x & mask111 小於 bucket 的數量
- 若 x & mask111 不小於 bucket 的數量
- 取 x 的較高位數再跟 mask011 進行 and 運算
綜合以上兩種情況可以得到以下程式碼
測驗 4
- 運作原理
一開始先將 x 減去 1 ,這樣就可以將問題轉成尋找 x 之中最高位的 1 。
程式中的 r 用來記錄總向右位移的位元數目。
利用二分搜尋的方式,尋找最高位的 1 所在的位置。
第一次先判斷 x 是否大於 0xff 來得知最高位在第 0~15 bit 之間還是在 16~31 bit 之間。若最高位在 16~31 bit 之間,則將 x 向右位移 16 位,下一次就只考慮最高位是在 0~15 bit 之間的何處,並且同時用 r 紀錄位移的數量。
接著以此類推,將 x 與 0xff 來做比較,藉此得知最高位在 0~7 bit 之間或是 8~15 bit 之間,並且用 r 紀錄位移的數量。
接著重複此過程直到範圍內剩下二個 bit 為止。
此時範圍內只剩下 0~1 bit 兩個位元。
首先將 r 跟 shift 的值相加 ( 運用 bitwiese or 運算速度較快 ) ,若最高位發生在第 1 個 bit 則要將答案再加一,因此再跟 x >> 1
做 or 運算。最後由於是向上取整,因此整個答案要再加上 1 。
- 支援x = 0
再最一開始用一個變數紀錄 x 是否為 0,若 x 為 0 則將答案乘以 0 ,若不為 0 則乘以 1 。