# 2023q1 Homework2 (quiz2)
contributed by < visitorckw >
## 測驗一
### 說明
其思想為從 x 的最高有效位開始直到最低有效位都設為 1 。
利用演算法之中的倍增法的思想來快速設定位元的值。
1. ```x |= x >> 1;``` 可以保證最高有效位以及其較其低一位的位元都設為1。
2. ```x |= x >> 2;``` 可以保證最高有效位以及其較其低三位的位元都設為1。
3. ```x |= x >> 4;``` 可以保證最高有效位以及其較其低七位的位元都設為1。
4. 以此類推直到全都做為為止。
### 改寫
```c
uint64_t next_pow2(uint64_t x)
{
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x |= x >> 32;
return ++x;
}
```
### 使用__builtin_clzl改寫
```c
uint64_t next_pow2(uint64_t x)
{
return 1 << (64 - __builtin_clzl(x));
}
```
## 測驗二
### 說明
透過迴圈從 1 開始跑到 n 。
變數 len 用來紀錄當前迴圈所尋訪到的變數 i 的二進位位元長度。
因此每當遇到 i 是 2 的冪時,就應該要將 len 的值增加 1 。
判斷的方法為:
```c
!(x & (x - 1))
```
然後將 i 的二進位串接到 ans 的尾端,其實作如下:
```c
ans = (i | (ans << len)) % M;
```
### 使用__builtin_{clz,ctz,ffs}改寫
判斷 i 是否為2的冪可以採用以下實作:
```c
!(i ^ (1 << __builtin_ctz(i)))
```
## 測驗三
```c
count = (1 << 3) * (len / 8) - count;
count += (len & 7) ? count_utf8((const char *) end, len & 7) : 0;
```
在 count 加上 __builtin_popcountll(t4) 過後,仍然需要對 count 進行調整。
此時的 count 所代表的是後續位元組數量,因此要將字串的長度減去後續位元組數量。
最後則是要處理不能被 8 整除的部份。
## 測驗四
```c
bool is_pattern(uint16_t x)
{
const uint16_t n = ~x + 1;
return (n ^ x) < x;
}
```
首先取 x 的二補數,可以用 ```~x + 1``` 或者 ```-x``` 。
二補數的效果相當於保持最低有效位元是 1 ,此外比最低有效位元更高的位元都取 not 。
若 x 的左側的 bits 都是 1 的話,在 x 跟 x 的二補數做 xor 操作過後,相當於只把最低有效位元設為 0 ,其餘位元皆維持不變,因此必定小於 x 。