目的: 檢驗學員對 bitwise 的認知
作答表單: 測驗 1-2 (針對 Linux 核心「設計」課程)
作答表單: 測驗 3-4 (針對 Linux 核心「實作」課程)
1
參照 你所不知道的 C 語言: bitwise 操作,考慮 next_pow2
可針對給定無號 64 位元數值 x
,找出最接近且大於等於 2 的冪的值,例如:
next_pow2(7)
= 8next_pow2(13)
= 16next_pow2(42)
= 64以下是可能的實作方式:
然而上述程式碼存在分支,於是我們可考慮建構以下「填補」位元表示中的 1
:
最初 x
是 0010000000000000
,經過一系列操作後,成為 0011111111111111
,亦即設定 (set,即指派為 1
) 自原本最高位元到最低位元中,所有的位元。
我們嘗試改寫為以下:
請補完程式碼,使其符合預期。作答規範:
AAAA
和 BBBB
皆為數值,且 AAAA
小於 BBBB
CCCC
為表示式延伸問題:
__builtin_clzl
改寫
int __builtin_clz (unsigned int x)
Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
int __builtin_clzl (unsigned long)
Similar to__builtin_clz
, except the argument type is unsigned long.
clz
內建函式已運用時,編譯器能否產生對應的 x86 指令?
提示: 可執行
cc -O2 -std=c99 -S next_pow2.c
並觀察產生的next_pow2.s
檔案,確認bsrq
指令 (表示 "Bit Scan Reverse")
2
LeetCode 1680. Concatenation of Consecutive Binary Numbers 給定一整數 ,回傳將 1 到 的二進位表示法依序串接在一起所得到的二進位字串,其所代表的十進位數字 mod 之值。
測試資料 1:
輸入: n = 1
輸出: 1
"1" 於二進位中對應著十進位中
1
的值
測試資料 2:
輸入: n = 3
輸出: 27
二進位中,1 、 2 、 3 對應著
1
,10
和11
。
將它們串接在一起,我們得到11011
,其對應著十進位數值27
測試資料 3:
輸入: n = 12
輸出: 505379714
串接結果為
1101110010111011110001001101010111100
該十進位值為118505380540
mod 後,結果為505379714
以下是可能的實作:
請補完程式碼,使其符合預期。作答規範:
DDDD
和 EEEE
皆為表示式延伸問題:
__builtin_{clz,ctz,ffs}
改寫,並改進 mod 的運算3
SIMD within a register (SWAR) 是軟體最佳化技巧之一,以下展示 SWAR 運用於 64 位元微處理器架構,原本判斷 2 個 32 位元寬度的整數是否都是奇數 (odd),可能會這樣撰寫:
但我們可先組合 (compound) 2 個 32 位元寬度的整數為 1 個 64 位元整數,再運用特製的 bitmask,從而減少運算量:
測試程式:
延伸閱讀: SIMD and SWAR Techniques
UTF-8 字元可由 1, 2, 3, 4 個位元組構成。其中單一位元組的 UTF-8 由 ASCII 字元構成,其 MSB 必為 0
。
UTF-8 的多位元組字元是由一個首位元組和 1, 2 或 3 個後續位元組 (continuation byte(s)) 所構成。後續位元組的最高 2 個位元會設定為 10
。對於首位元組,最高的 2 個位元始終為 11
,下表展現多位元組字元的規則:
ASCII | 0xxx.xxxx |
---|---|
2 bytes | 110x.xxxx 10xx.xxxx |
3 bytes | 1110.xxxx 10xx.xxxx 10xx.xxxx |
4 bytes | 1111.0xxx 10xx.xxxx 10xx.xxxx 10xx.xxxx |
若輸入的字串是一個有效的 UTF-8 序列,則計算其中的後續位元組數量,並將此數字從總字串長度中減去,即可確定字元數量。
將位元組轉換為 (以二補數表示) 有號整數的位元組,並與 "magic number" 進行比較,就足以確定它是否為後續位元組。對應的程式碼如下:
SWAR 通常不易實作,因此,我們觀察它們的位元模式:(從最低位元起算) 第 7 位元為 1,且第 6 位元為 0。於是我們可採用以下表示式:
再計算 (使用 population count 指令) 有多少位元組裡頭的 1
(即具有此屬性)。
not bit6
)
not bit6 and bit7
popcount(t4)
SWAR 實作如下:
請補完程式碼,使其運作符合預期。作答規範:
AAAA
, BBBB
, CCCC
, DDDD
皆為常數延伸閱讀:
延伸問題:
4
以下程式碼可判定 16 位元無號整數是否符合特定樣式 (pattern):
符合上述程式碼的樣式,如下:
改寫上述程式碼,使其達到等價行為,但更精簡有效。
EEEE = ?
FFFF = ?
延伸問題: