contributed by < Jerejere0808 >
將最高位元數下的 bits 改為 1 ,最後再加 1 進位,得到大於其值最接近的2的冪。
AAAA = 1
BBBB = 32
CCCC = x + 1
用 __builtin_clz() 簡化程式碼
上為產生的 x86 指令 其中指令 "bsrl %edi, %edi" 在暫存器 %edi 的值執行了 bit scan reverse operation ,尋找 %edi 值中最高位的設定位元(即最左邊的1位元),並將其位置存儲在 %edi 中。
在 Linux 核心原始程式碼找出類似的使用案例並解釋:
DDD = i & (i - 1) == 0
判斷 i 是否為二的冪,ex: 100 & 011 = 0。 若為真 len 就加一,因為會多出一個bit
EEEE = (ans<<len) 移出 len 個 bits 的空間
用 __builtin_ctz() 改寫,若目前 len 跟 二進位的 i 右側連續的 0 bits 數量一樣就代表 len 必須加一 ans 才可以挪出足夠的空間給二進位的 i (因為i最前面會多出一個 1 bit)
改進 mod 1e9 + 7 的運算 (還在思考)
因為用了 SWAR 增加效率,變成一次處理 64 bits(8 個 bytes),所以先算最大 8 的倍數的 bytes 數量其已經利用 SWAR 算出 continuation byte(s) 數量 所以 count 就變成總量減去continuation byte(s) 數量也就是去除 continuation byte(s) 的bytes數 剩下不能利用 SWAR 的就使用 count_utf8 求出去除 continuation byte(s) 的bytes數,最後將其相加。
AAAA = 3
BBBB = 7
CCCC = 7
在 Linux 核心原始程式碼找出 UTF-8 和 Unicode 相關字串處理的程式碼(還在找應該會從/include/linux/unicode.h 挑選)
EEEE = ~x + 1
FFFF = x
符合 pattern 的二進位數在有效最大位數一定是 1' bit,且跟最低位的 1 之間不能有 0' bit,如也就是說若出現 1…01…0 這個情況就不符合,~x + 1 會讓 1…01…0 變成 1…11…0 透過(n ^ x) 會變成 1…10…0 會比原本 x 大。若是原本符合 pattern 的 x 透過這個操作就會變小。(想很久= =)